75abf435e6a528c093e0867d2daafe964388f0f4
[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 <iostream>
11
12 static VM *TheVM = 0;
13
14 // CompilationCallback - Invoked the first time that a call site is found,
15 // which causes lazy compilation of the target function.
16 // 
17 void VM::CompilationCallback() {
18 #if defined(i386) || defined(__i386__) || defined(__x86__)
19   unsigned *StackPtr = (unsigned*)__builtin_frame_address(0);
20   unsigned RetAddr = (unsigned)__builtin_return_address(0);
21
22   assert(StackPtr[1] == RetAddr &&
23          "Could not find return address on the stack!");
24
25   // The call instruction should have pushed the return value onto the stack...
26   RetAddr -= 4;  // Backtrack to the reference itself...
27
28   DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << RetAddr
29                   << " ESP=0x" << (unsigned)StackPtr << std::dec
30                   << ": Resolving call to function: "
31                   << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n");
32
33   // Sanity check to make sure this really is a call instruction...
34   assert(((unsigned char*)RetAddr)[-1] == 0xE8 && "Not a call instr!");
35   
36   unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RetAddr);
37
38   // Rewrite the call target... so that we don't fault every time we execute
39   // the call.
40   *(unsigned*)RetAddr = NewVal-RetAddr-4;    
41
42   // Change the return address to reexecute the call instruction...
43   StackPtr[1] -= 5;
44 #else
45   abort();
46 #endif
47 }
48
49
50 void VM::registerCallback() {
51   TheVM = this;
52 }
53
54