JIT.cpp revision e2947531280503a4e73e8d94a6161f68bea857a7
1//===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This tool implements a just-in-time compiler for LLVM, allowing direct 11// execution of LLVM bytecode in an efficient manner. 12// 13//===----------------------------------------------------------------------===// 14 15#include "JIT.h" 16#include "llvm/DerivedTypes.h" 17#include "llvm/Function.h" 18#include "llvm/GlobalVariable.h" 19#include "llvm/ModuleProvider.h" 20#include "llvm/CodeGen/MachineCodeEmitter.h" 21#include "llvm/CodeGen/MachineFunction.h" 22#include "llvm/ExecutionEngine/GenericValue.h" 23#include "llvm/Target/TargetMachine.h" 24#include "llvm/Target/TargetJITInfo.h" 25#include "Support/DynamicLinker.h" 26#include <iostream> 27 28using namespace llvm; 29 30JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji) 31 : ExecutionEngine(MP), TM(tm), TJI(tji), PM(MP) { 32 setTargetData(TM.getTargetData()); 33 34 // Initialize MCE 35 MCE = createEmitter(*this); 36 37 // Add target data 38 PM.add (new TargetData (TM.getTargetData ())); 39 40 // Compile LLVM Code down to machine code in the intermediate representation 41 TJI.addPassesToJITCompile(PM); 42 43 // Turn the machine code intermediate representation into bytes in memory that 44 // may be executed. 45 if (TM.addPassesToEmitMachineCode(PM, *MCE)) { 46 std::cerr << "lli: target '" << TM.getName() 47 << "' doesn't support machine code emission!\n"; 48 abort(); 49 } 50} 51 52JIT::~JIT() { 53 delete MCE; 54 delete &TM; 55} 56 57/// run - Start execution with the specified function and arguments. 58/// 59GenericValue JIT::runFunction(Function *F, 60 const std::vector<GenericValue> &ArgValues) { 61 assert (F && "Function *F was null at entry to run()"); 62 GenericValue rv; 63 64 if (ArgValues.size() == 3) { 65 int (*PF)(int, char **, const char **) = 66 (int(*)(int, char **, const char **))getPointerToFunction(F); 67 assert(PF && "Pointer to fn's code was null after getPointerToFunction"); 68 69 // Call the function. 70 int ExitCode = PF(ArgValues[0].IntVal, (char **) GVTOP (ArgValues[1]), 71 (const char **) GVTOP (ArgValues[2])); 72 73 rv.IntVal = ExitCode; 74 } else { 75 // FIXME: This code should handle a couple of common cases efficiently, but 76 // it should also implement the general case by code-gening a new anonymous 77 // nullary function to call. 78 assert(ArgValues.size() == 1); 79 void (*PF)(int) = (void(*)(int))getPointerToFunction(F); 80 assert(PF && "Pointer to fn's code was null after getPointerToFunction"); 81 PF(ArgValues[0].IntVal); 82 } 83 84 return rv; 85} 86 87/// runJITOnFunction - Run the FunctionPassManager full of 88/// just-in-time compilation passes on F, hopefully filling in 89/// GlobalAddress[F] with the address of F's machine code. 90/// 91void JIT::runJITOnFunction(Function *F) { 92 static bool isAlreadyCodeGenerating = false; 93 assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"); 94 95 // JIT the function 96 isAlreadyCodeGenerating = true; 97 PM.run(*F); 98 isAlreadyCodeGenerating = false; 99 100 // If the function referred to a global variable that had not yet been 101 // emitted, it allocates memory for the global, but doesn't emit it yet. Emit 102 // all of these globals now. 103 while (!PendingGlobals.empty()) { 104 const GlobalVariable *GV = PendingGlobals.back(); 105 PendingGlobals.pop_back(); 106 EmitGlobalVariable(GV); 107 } 108} 109 110/// getPointerToFunction - This method is used to get the address of the 111/// specified function, compiling it if neccesary. 112/// 113void *JIT::getPointerToFunction(Function *F) { 114 if (void *Addr = getPointerToGlobalIfAvailable(F)) 115 return Addr; // Check if function already code gen'd 116 117 // Make sure we read in the function if it exists in this Module 118 try { 119 MP->materializeFunction(F); 120 } catch ( std::string& errmsg ) { 121 std::cerr << "Error parsing bytecode file: " << errmsg << "\n"; 122 abort(); 123 } catch (...) { 124 std::cerr << "Error parsing bytecode file!\n"; 125 abort(); 126 } 127 128 if (F->isExternal()) { 129 void *Addr = getPointerToNamedFunction(F->getName()); 130 addGlobalMapping(F, Addr); 131 return Addr; 132 } 133 134 runJITOnFunction(F); 135 136 void *Addr = getPointerToGlobalIfAvailable(F); 137 assert(Addr && "Code generation didn't add function to GlobalAddress table!"); 138 return Addr; 139} 140 141// getPointerToFunctionOrStub - If the specified function has been 142// code-gen'd, return a pointer to the function. If not, compile it, or use 143// a stub to implement lazy compilation if available. 144// 145void *JIT::getPointerToFunctionOrStub(Function *F) { 146 // If we have already code generated the function, just return the address. 147 if (void *Addr = getPointerToGlobalIfAvailable(F)) 148 return Addr; 149 150 // If the target supports "stubs" for functions, get a stub now. 151 if (void *Ptr = TJI.getJITStubForFunction(F, *MCE)) 152 return Ptr; 153 154 // Otherwise, if the target doesn't support it, just codegen the function. 155 return getPointerToFunction(F); 156} 157 158/// getOrEmitGlobalVariable - Return the address of the specified global 159/// variable, possibly emitting it to memory if needed. This is used by the 160/// Emitter. 161void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { 162 void *Ptr = getPointerToGlobalIfAvailable(GV); 163 if (Ptr) return Ptr; 164 165 // If the global is external, just remember the address. 166 if (GV->isExternal()) { 167 Ptr = GetAddressOfSymbol(GV->getName().c_str()); 168 if (Ptr == 0) { 169 std::cerr << "Could not resolve external global address: " 170 << GV->getName() << "\n"; 171 abort(); 172 } 173 } else { 174 // If the global hasn't been emitted to memory yet, allocate space. We will 175 // actually initialize the global after current function has finished 176 // compilation. 177 Ptr =new char[getTargetData().getTypeSize(GV->getType()->getElementType())]; 178 PendingGlobals.push_back(GV); 179 } 180 addGlobalMapping(GV, Ptr); 181 return Ptr; 182} 183 184 185/// recompileAndRelinkFunction - This method is used to force a function 186/// which has already been compiled, to be compiled again, possibly 187/// after it has been modified. Then the entry to the old copy is overwritten 188/// with a branch to the new copy. If there was no old copy, this acts 189/// just like JIT::getPointerToFunction(). 190/// 191void *JIT::recompileAndRelinkFunction(Function *F) { 192 void *OldAddr = getPointerToGlobalIfAvailable(F); 193 194 // If it's not already compiled there is no reason to patch it up. 195 if (OldAddr == 0) { return getPointerToFunction(F); } 196 197 // Delete the old function mapping. 198 addGlobalMapping(F, 0); 199 200 // Recodegen the function 201 runJITOnFunction(F); 202 203 // Update state, forward the old function to the new function. 204 void *Addr = getPointerToGlobalIfAvailable(F); 205 assert(Addr && "Code generation didn't add function to GlobalAddress table!"); 206 TJI.replaceMachineCodeForFunction(OldAddr, Addr); 207 return Addr; 208} 209