| Eric Christopher | d619067 | 2011-03-22 08:49:56 +0000 | [diff] [blame] | 1 | //===-- MCJIT.cpp - MC-based Just-in-Time Compiler --------------------------===// | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
|  | 10 | #include "MCJIT.h" | 
| Jim Grosbach | 34714a0 | 2011-03-22 18:05:27 +0000 | [diff] [blame] | 11 | #include "llvm/DerivedTypes.h" | 
| Jim Grosbach | 31649e6 | 2011-03-18 22:48:41 +0000 | [diff] [blame] | 12 | #include "llvm/Function.h" | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 13 | #include "llvm/ExecutionEngine/GenericValue.h" | 
|  | 14 | #include "llvm/ExecutionEngine/MCJIT.h" | 
| Jim Grosbach | f922910 | 2011-03-22 01:06:42 +0000 | [diff] [blame] | 15 | #include "llvm/ExecutionEngine/JITMemoryManager.h" | 
|  | 16 | #include "llvm/MC/MCAsmInfo.h" | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 17 | #include "llvm/Support/ErrorHandling.h" | 
| Michael J. Spencer | 1f6efa3 | 2010-11-29 18:16:10 +0000 | [diff] [blame] | 18 | #include "llvm/Support/DynamicLibrary.h" | 
| Jim Grosbach | f922910 | 2011-03-22 01:06:42 +0000 | [diff] [blame] | 19 | #include "llvm/Support/MemoryBuffer.h" | 
| Jim Grosbach | 31649e6 | 2011-03-18 22:48:41 +0000 | [diff] [blame] | 20 | #include "llvm/Target/TargetData.h" | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 21 |  | 
|  | 22 | using namespace llvm; | 
|  | 23 |  | 
|  | 24 | namespace { | 
|  | 25 |  | 
|  | 26 | static struct RegisterJIT { | 
|  | 27 | RegisterJIT() { MCJIT::Register(); } | 
|  | 28 | } JITRegistrator; | 
|  | 29 |  | 
|  | 30 | } | 
|  | 31 |  | 
|  | 32 | extern "C" void LLVMLinkInMCJIT() { | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | ExecutionEngine *MCJIT::createJIT(Module *M, | 
|  | 36 | std::string *ErrorStr, | 
|  | 37 | JITMemoryManager *JMM, | 
|  | 38 | CodeGenOpt::Level OptLevel, | 
|  | 39 | bool GVsWithCode, | 
|  | 40 | CodeModel::Model CMM, | 
|  | 41 | StringRef MArch, | 
|  | 42 | StringRef MCPU, | 
|  | 43 | const SmallVectorImpl<std::string>& MAttrs) { | 
|  | 44 | // Try to register the program as a source of symbols to resolve against. | 
|  | 45 | // | 
|  | 46 | // FIXME: Don't do this here. | 
|  | 47 | sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); | 
|  | 48 |  | 
|  | 49 | // Pick a target either via -march or by guessing the native arch. | 
|  | 50 | // | 
|  | 51 | // FIXME: This should be lifted out of here, it isn't something which should | 
|  | 52 | // be part of the JIT policy, rather the burden for this selection should be | 
|  | 53 | // pushed to clients. | 
|  | 54 | TargetMachine *TM = MCJIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); | 
|  | 55 | if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; | 
|  | 56 | TM->setCodeModel(CMM); | 
|  | 57 |  | 
|  | 58 | // If the target supports JIT code generation, create the JIT. | 
|  | 59 | if (TargetJITInfo *TJ = TM->getJITInfo()) | 
| Jim Grosbach | 31649e6 | 2011-03-18 22:48:41 +0000 | [diff] [blame] | 60 | return new MCJIT(M, TM, *TJ, JMM, OptLevel, GVsWithCode); | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 61 |  | 
|  | 62 | if (ErrorStr) | 
|  | 63 | *ErrorStr = "target does not support JIT code generation"; | 
|  | 64 | return 0; | 
|  | 65 | } | 
|  | 66 |  | 
| Jim Grosbach | 31649e6 | 2011-03-18 22:48:41 +0000 | [diff] [blame] | 67 | MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 68 | JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, | 
|  | 69 | bool AllocateGVsWithCode) | 
| Jim Grosbach | 31649e6 | 2011-03-18 22:48:41 +0000 | [diff] [blame] | 70 | : ExecutionEngine(m), TM(tm), M(m), OS(Buffer) { | 
|  | 71 |  | 
|  | 72 | PM.add(new TargetData(*TM->getTargetData())); | 
|  | 73 |  | 
|  | 74 | // Turn the machine code intermediate representation into bytes in memory | 
|  | 75 | // that may be executed. | 
|  | 76 | if (TM->addPassesToEmitMC(PM, Ctx, OS, CodeGenOpt::Default, false)) { | 
|  | 77 | report_fatal_error("Target does not support MC emission!"); | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | // Initialize passes. | 
|  | 81 | ExecutionEngine::addModule(M); | 
|  | 82 | // FIXME: When we support multiple modules, we'll want to move the code | 
|  | 83 | // gen and finalization out of the constructor here and do it more | 
|  | 84 | // on-demand as part of getPointerToFunction(). | 
|  | 85 | PM.run(*M); | 
|  | 86 | // Flush the output buffer so the SmallVector gets its data. | 
|  | 87 | OS.flush(); | 
| Jim Grosbach | f922910 | 2011-03-22 01:06:42 +0000 | [diff] [blame] | 88 |  | 
|  | 89 | // Load the object into the dynamic linker. | 
|  | 90 | // FIXME: It would be nice to avoid making yet another copy. | 
|  | 91 | MemoryBuffer *MB = MemoryBuffer::getMemBufferCopy(StringRef(Buffer.data(), | 
|  | 92 | Buffer.size())); | 
| Jim Grosbach | 8086f3b | 2011-03-23 19:51:34 +0000 | [diff] [blame^] | 93 | if (Dyld.loadObject(MB)) | 
|  | 94 | report_fatal_error(Dyld.getErrorString()); | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 95 | } | 
|  | 96 |  | 
|  | 97 | MCJIT::~MCJIT() { | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { | 
|  | 101 | report_fatal_error("not yet implemented"); | 
|  | 102 | return 0; | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | void *MCJIT::getPointerToFunction(Function *F) { | 
| Jim Grosbach | 34714a0 | 2011-03-22 18:05:27 +0000 | [diff] [blame] | 106 | if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { | 
|  | 107 | bool AbortOnFailure = !F->hasExternalWeakLinkage(); | 
|  | 108 | void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure); | 
|  | 109 | addGlobalMapping(F, Addr); | 
|  | 110 | return Addr; | 
|  | 111 | } | 
|  | 112 |  | 
| Jim Grosbach | f922910 | 2011-03-22 01:06:42 +0000 | [diff] [blame] | 113 | Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName(); | 
|  | 114 | return Dyld.getSymbolAddress(Name.str()); | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 115 | } | 
|  | 116 |  | 
|  | 117 | void *MCJIT::recompileAndRelinkFunction(Function *F) { | 
|  | 118 | report_fatal_error("not yet implemented"); | 
|  | 119 | } | 
|  | 120 |  | 
|  | 121 | void MCJIT::freeMachineCodeForFunction(Function *F) { | 
|  | 122 | report_fatal_error("not yet implemented"); | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | GenericValue MCJIT::runFunction(Function *F, | 
|  | 126 | const std::vector<GenericValue> &ArgValues) { | 
| Jim Grosbach | 34714a0 | 2011-03-22 18:05:27 +0000 | [diff] [blame] | 127 | assert(F && "Function *F was null at entry to run()"); | 
|  | 128 |  | 
| Jim Grosbach | 31649e6 | 2011-03-18 22:48:41 +0000 | [diff] [blame] | 129 | void *FPtr = getPointerToFunction(F); | 
| Jim Grosbach | 34714a0 | 2011-03-22 18:05:27 +0000 | [diff] [blame] | 130 | assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); | 
|  | 131 | const FunctionType *FTy = F->getFunctionType(); | 
|  | 132 | const Type *RetTy = FTy->getReturnType(); | 
|  | 133 |  | 
|  | 134 | assert((FTy->getNumParams() == ArgValues.size() || | 
|  | 135 | (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && | 
|  | 136 | "Wrong number of arguments passed into function!"); | 
|  | 137 | assert(FTy->getNumParams() == ArgValues.size() && | 
|  | 138 | "This doesn't support passing arguments through varargs (yet)!"); | 
|  | 139 |  | 
|  | 140 | // Handle some common cases first.  These cases correspond to common `main' | 
|  | 141 | // prototypes. | 
|  | 142 | if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { | 
|  | 143 | switch (ArgValues.size()) { | 
|  | 144 | case 3: | 
|  | 145 | if (FTy->getParamType(0)->isIntegerTy(32) && | 
|  | 146 | FTy->getParamType(1)->isPointerTy() && | 
|  | 147 | FTy->getParamType(2)->isPointerTy()) { | 
|  | 148 | int (*PF)(int, char **, const char **) = | 
|  | 149 | (int(*)(int, char **, const char **))(intptr_t)FPtr; | 
|  | 150 |  | 
|  | 151 | // Call the function. | 
|  | 152 | GenericValue rv; | 
|  | 153 | rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), | 
|  | 154 | (char **)GVTOP(ArgValues[1]), | 
|  | 155 | (const char **)GVTOP(ArgValues[2]))); | 
|  | 156 | return rv; | 
|  | 157 | } | 
|  | 158 | break; | 
|  | 159 | case 2: | 
|  | 160 | if (FTy->getParamType(0)->isIntegerTy(32) && | 
|  | 161 | FTy->getParamType(1)->isPointerTy()) { | 
|  | 162 | int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; | 
|  | 163 |  | 
|  | 164 | // Call the function. | 
|  | 165 | GenericValue rv; | 
|  | 166 | rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), | 
|  | 167 | (char **)GVTOP(ArgValues[1]))); | 
|  | 168 | return rv; | 
|  | 169 | } | 
|  | 170 | break; | 
|  | 171 | case 1: | 
|  | 172 | if (FTy->getNumParams() == 1 && | 
|  | 173 | FTy->getParamType(0)->isIntegerTy(32)) { | 
|  | 174 | GenericValue rv; | 
|  | 175 | int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; | 
|  | 176 | rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); | 
|  | 177 | return rv; | 
|  | 178 | } | 
|  | 179 | break; | 
|  | 180 | } | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | // Handle cases where no arguments are passed first. | 
|  | 184 | if (ArgValues.empty()) { | 
|  | 185 | GenericValue rv; | 
|  | 186 | switch (RetTy->getTypeID()) { | 
|  | 187 | default: llvm_unreachable("Unknown return type for function call!"); | 
|  | 188 | case Type::IntegerTyID: { | 
|  | 189 | unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); | 
|  | 190 | if (BitWidth == 1) | 
|  | 191 | rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); | 
|  | 192 | else if (BitWidth <= 8) | 
|  | 193 | rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); | 
|  | 194 | else if (BitWidth <= 16) | 
|  | 195 | rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); | 
|  | 196 | else if (BitWidth <= 32) | 
|  | 197 | rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); | 
|  | 198 | else if (BitWidth <= 64) | 
|  | 199 | rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); | 
|  | 200 | else | 
|  | 201 | llvm_unreachable("Integer types > 64 bits not supported"); | 
|  | 202 | return rv; | 
|  | 203 | } | 
|  | 204 | case Type::VoidTyID: | 
|  | 205 | rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); | 
|  | 206 | return rv; | 
|  | 207 | case Type::FloatTyID: | 
|  | 208 | rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); | 
|  | 209 | return rv; | 
|  | 210 | case Type::DoubleTyID: | 
|  | 211 | rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); | 
|  | 212 | return rv; | 
|  | 213 | case Type::X86_FP80TyID: | 
|  | 214 | case Type::FP128TyID: | 
|  | 215 | case Type::PPC_FP128TyID: | 
|  | 216 | llvm_unreachable("long double not supported yet"); | 
|  | 217 | return rv; | 
|  | 218 | case Type::PointerTyID: | 
|  | 219 | return PTOGV(((void*(*)())(intptr_t)FPtr)()); | 
|  | 220 | } | 
|  | 221 | } | 
|  | 222 |  | 
|  | 223 | assert("Full-featured argument passing not supported yet!"); | 
| Daniel Dunbar | 6aec298 | 2010-11-17 16:06:43 +0000 | [diff] [blame] | 224 | return GenericValue(); | 
|  | 225 | } |