Initial checkin of new LLI with JIT compiler
[oota-llvm.git] / lib / ExecutionEngine / JIT / Callback.cpp
1 //===-- Callback.cpp - Trap handler for function resolution ---------------===//
2 //
3 // This file defines the SIGSEGV handler which is invoked when a reference to a
4 // non-codegen'd function is found.
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "VM.h"
9 #include "Support/Statistic.h"
10 #include <signal.h>
11 #include <ucontext.h>
12 #include <iostream>
13
14 static VM *TheVM = 0;
15
16 static void TrapHandler(int TN, siginfo_t *SI, ucontext_t *ucp) {
17   assert(TN == SIGSEGV && "Should be SIGSEGV!");
18
19 #ifdef REG_EIP   /* this code does not compile on Sparc! */
20   if (SI->si_code != SEGV_MAPERR || SI->si_addr != 0 ||
21       ucp->uc_mcontext.gregs[REG_EIP] != 0) {
22     std::cerr << "Bad SEGV encountered!\n";
23     abort();
24   }
25
26   // The call instruction should have pushed the return value onto the stack...
27   unsigned RefAddr = *(unsigned*)ucp->uc_mcontext.gregs[REG_ESP];
28   RefAddr -= 4;  // Backtrack to the reference itself...
29
30   DEBUG(std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr
31                   << " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec
32                   << ": Resolving call to function: "
33                   << TheVM->getFunctionReferencedName((void*)RefAddr) << "\n");
34
35   // Sanity check to make sure this really is a call instruction...
36   assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!");
37   
38   unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RefAddr);
39
40   // Rewrite the call target... so that we don't fault every time we execute
41   // the call.
42   *(unsigned*)RefAddr = NewVal-RefAddr-4;    
43
44   // Change the instruction pointer to be the real target of the call...
45   ucp->uc_mcontext.gregs[REG_EIP] = NewVal;
46
47 #endif
48 }
49
50
51 void VM::registerCallback() {
52   TheVM = this;
53
54   // Register the signal handler...
55   struct sigaction SA;
56   SA.sa_sigaction = (void (*)(int, siginfo_t*, void*))TrapHandler;
57   sigfillset(&SA.sa_mask);               // Block all signals while codegen'ing
58   SA.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; // Get siginfo
59   sigaction(SIGSEGV, &SA, 0);            // Install the handler
60 }
61
62