LLVM API Documentation
00001 //===-- X86JITInfo.cpp - Implement the JIT interfaces for the X86 target --===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the JIT interfaces for the X86 target. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #define DEBUG_TYPE "jit" 00015 #include "X86JITInfo.h" 00016 #include "X86Relocations.h" 00017 #include "llvm/CodeGen/MachineCodeEmitter.h" 00018 #include "llvm/Config/alloca.h" 00019 #include <cstdlib> 00020 #include <iostream> 00021 using namespace llvm; 00022 00023 #ifdef _MSC_VER 00024 extern "C" void *_AddressOfReturnAddress(void); 00025 #pragma intrinsic(_AddressOfReturnAddress) 00026 #endif 00027 00028 void X86JITInfo::replaceMachineCodeForFunction(void *Old, void *New) { 00029 unsigned char *OldByte = (unsigned char *)Old; 00030 *OldByte++ = 0xE9; // Emit JMP opcode. 00031 unsigned *OldWord = (unsigned *)OldByte; 00032 unsigned NewAddr = (intptr_t)New; 00033 unsigned OldAddr = (intptr_t)OldWord; 00034 *OldWord = NewAddr - OldAddr - 4; // Emit PC-relative addr of New code. 00035 } 00036 00037 00038 /// JITCompilerFunction - This contains the address of the JIT function used to 00039 /// compile a function lazily. 00040 static TargetJITInfo::JITCompilerFn JITCompilerFunction; 00041 00042 // Provide a wrapper for X86CompilationCallback2 that saves non-traditional 00043 // callee saved registers, for the fastcc calling convention. 00044 extern "C" { 00045 #if defined(__i386__) || defined(i386) || defined(_M_IX86) 00046 #ifndef _MSC_VER 00047 void X86CompilationCallback(void); 00048 asm( 00049 ".text\n" 00050 ".align 8\n" 00051 #if defined(__CYGWIN__) || defined(__APPLE__) || defined(__MINGW32__) 00052 ".globl _X86CompilationCallback\n" 00053 "_X86CompilationCallback:\n" 00054 #else 00055 ".globl X86CompilationCallback\n" 00056 "X86CompilationCallback:\n" 00057 #endif 00058 "pushl %ebp\n" 00059 "movl %esp, %ebp\n" // Standard prologue 00060 #if FASTCC_NUM_INT_ARGS_INREGS > 0 00061 "pushl %eax\n" 00062 "pushl %edx\n" // Save EAX/EDX 00063 #endif 00064 #if defined(__APPLE__) 00065 "andl $-16, %esp\n" // Align ESP on 16-byte boundary 00066 #endif 00067 "subl $16, %esp\n" 00068 "movl 4(%ebp), %eax\n" // Pass prev frame and return address 00069 "movl %eax, 4(%esp)\n" 00070 "movl %ebp, (%esp)\n" 00071 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__APPLE__) 00072 "call _X86CompilationCallback2\n" 00073 #else 00074 "call X86CompilationCallback2\n" 00075 #endif 00076 "movl %ebp, %esp\n" // Restore ESP 00077 #if FASTCC_NUM_INT_ARGS_INREGS > 0 00078 "subl $8, %esp\n" 00079 "popl %edx\n" 00080 "popl %eax\n" 00081 #endif 00082 "popl %ebp\n" 00083 "ret\n"); 00084 #else 00085 void X86CompilationCallback2(void); 00086 00087 _declspec(naked) void X86CompilationCallback(void) { 00088 __asm { 00089 push eax 00090 push edx 00091 call X86CompilationCallback2 00092 pop edx 00093 pop eax 00094 ret 00095 } 00096 } 00097 #endif // _MSC_VER 00098 00099 #else // Not an i386 host 00100 void X86CompilationCallback() { 00101 std::cerr << "Cannot call X86CompilationCallback() on a non-x86 arch!\n"; 00102 abort(); 00103 } 00104 #endif 00105 } 00106 00107 /// X86CompilationCallback - This is the target-specific function invoked by the 00108 /// function stub when we did not know the real target of a call. This function 00109 /// must locate the start of the stub or call site and pass it into the JIT 00110 /// compiler function. 00111 #ifdef _MSC_VER 00112 extern "C" void X86CompilationCallback2() { 00113 assert(sizeof(size_t) == 4); // FIXME: handle Win64 00114 unsigned *RetAddrLoc = (unsigned *)_AddressOfReturnAddress(); 00115 RetAddrLoc += 3; // skip over ret addr, edx, eax 00116 unsigned RetAddr = *RetAddrLoc; 00117 #else 00118 extern "C" void X86CompilationCallback2(intptr_t *StackPtr, intptr_t RetAddr) { 00119 intptr_t *RetAddrLoc = &StackPtr[1]; 00120 #endif 00121 assert(*RetAddrLoc == RetAddr && 00122 "Could not find return address on the stack!"); 00123 00124 // It's a stub if there is an interrupt marker after the call. 00125 bool isStub = ((unsigned char*)(intptr_t)RetAddr)[0] == 0xCD; 00126 00127 // The call instruction should have pushed the return value onto the stack... 00128 RetAddr -= 4; // Backtrack to the reference itself... 00129 00130 #if 0 00131 DEBUG(std::cerr << "In callback! Addr=" << (void*)RetAddr 00132 << " ESP=" << (void*)StackPtr 00133 << ": Resolving call to function: " 00134 << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n"); 00135 #endif 00136 00137 // Sanity check to make sure this really is a call instruction. 00138 assert(((unsigned char*)(intptr_t)RetAddr)[-1] == 0xE8 &&"Not a call instr!"); 00139 00140 unsigned NewVal = (intptr_t)JITCompilerFunction((void*)(intptr_t)RetAddr); 00141 00142 // Rewrite the call target... so that we don't end up here every time we 00143 // execute the call. 00144 *(unsigned*)(intptr_t)RetAddr = NewVal-RetAddr-4; 00145 00146 if (isStub) { 00147 // If this is a stub, rewrite the call into an unconditional branch 00148 // instruction so that two return addresses are not pushed onto the stack 00149 // when the requested function finally gets called. This also makes the 00150 // 0xCD byte (interrupt) dead, so the marker doesn't effect anything. 00151 ((unsigned char*)(intptr_t)RetAddr)[-1] = 0xE9; 00152 } 00153 00154 // Change the return address to reexecute the call instruction... 00155 *RetAddrLoc -= 5; 00156 } 00157 00158 TargetJITInfo::LazyResolverFn 00159 X86JITInfo::getLazyResolverFunction(JITCompilerFn F) { 00160 JITCompilerFunction = F; 00161 return X86CompilationCallback; 00162 } 00163 00164 void *X86JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) { 00165 // Note, we cast to intptr_t here to silence a -pedantic warning that 00166 // complains about casting a function pointer to a normal pointer. 00167 if (Fn != (void*)(intptr_t)X86CompilationCallback) { 00168 MCE.startFunctionStub(5); 00169 MCE.emitByte(0xE9); 00170 MCE.emitWordLE((intptr_t)Fn-MCE.getCurrentPCValue()-4); 00171 return MCE.finishFunctionStub(0); 00172 } 00173 00174 MCE.startFunctionStub(6); 00175 MCE.emitByte(0xE8); // Call with 32 bit pc-rel destination... 00176 00177 MCE.emitWordLE((intptr_t)Fn-MCE.getCurrentPCValue()-4); 00178 00179 MCE.emitByte(0xCD); // Interrupt - Just a marker identifying the stub! 00180 return MCE.finishFunctionStub(0); 00181 } 00182 00183 /// relocate - Before the JIT can run a block of code that has been emitted, 00184 /// it must rewrite the code to contain the actual addresses of any 00185 /// referenced global symbols. 00186 void X86JITInfo::relocate(void *Function, MachineRelocation *MR, 00187 unsigned NumRelocs, unsigned char* GOTBase) { 00188 for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { 00189 void *RelocPos = (char*)Function + MR->getMachineCodeOffset(); 00190 intptr_t ResultPtr = (intptr_t)MR->getResultPointer(); 00191 switch ((X86::RelocationType)MR->getRelocationType()) { 00192 case X86::reloc_pcrel_word: 00193 // PC relative relocation, add the relocated value to the value already in 00194 // memory, after we adjust it for where the PC is. 00195 ResultPtr = ResultPtr-(intptr_t)RelocPos-4; 00196 *((intptr_t*)RelocPos) += ResultPtr; 00197 break; 00198 case X86::reloc_absolute_word: 00199 // Absolute relocation, just add the relocated value to the value already 00200 // in memory. 00201 *((intptr_t*)RelocPos) += ResultPtr; 00202 break; 00203 } 00204 } 00205 } 00206 00207 void X86JITInfo::resolveBBRefs(MachineCodeEmitter &MCE) { 00208 // Resolve all forward branches now. 00209 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { 00210 unsigned Location = MCE.getMachineBasicBlockAddress(BBRefs[i].first); 00211 intptr_t Ref = BBRefs[i].second; 00212 *((unsigned*)Ref) = Location-Ref-4; 00213 } 00214 BBRefs.clear(); 00215 }