| //===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "OrcMCJITReplacement.h" | |
| #include "llvm/ExecutionEngine/GenericValue.h" | |
| namespace { | |
| static struct RegisterJIT { | |
| RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); } | |
| } JITRegistrator; | |
| } | |
| extern "C" void LLVMLinkInOrcMCJITReplacement() {} | |
| namespace llvm { | |
| namespace orc { | |
| GenericValue | |
| OrcMCJITReplacement::runFunction(Function *F, | |
| ArrayRef<GenericValue> ArgValues) { | |
| assert(F && "Function *F was null at entry to run()"); | |
| void *FPtr = getPointerToFunction(F); | |
| assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); | |
| FunctionType *FTy = F->getFunctionType(); | |
| Type *RetTy = FTy->getReturnType(); | |
| assert((FTy->getNumParams() == ArgValues.size() || | |
| (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && | |
| "Wrong number of arguments passed into function!"); | |
| assert(FTy->getNumParams() == ArgValues.size() && | |
| "This doesn't support passing arguments through varargs (yet)!"); | |
| // Handle some common cases first. These cases correspond to common `main' | |
| // prototypes. | |
| if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { | |
| switch (ArgValues.size()) { | |
| case 3: | |
| if (FTy->getParamType(0)->isIntegerTy(32) && | |
| FTy->getParamType(1)->isPointerTy() && | |
| FTy->getParamType(2)->isPointerTy()) { | |
| int (*PF)(int, char **, const char **) = | |
| (int (*)(int, char **, const char **))(intptr_t)FPtr; | |
| // Call the function. | |
| GenericValue rv; | |
| rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), | |
| (char **)GVTOP(ArgValues[1]), | |
| (const char **)GVTOP(ArgValues[2]))); | |
| return rv; | |
| } | |
| break; | |
| case 2: | |
| if (FTy->getParamType(0)->isIntegerTy(32) && | |
| FTy->getParamType(1)->isPointerTy()) { | |
| int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr; | |
| // Call the function. | |
| GenericValue rv; | |
| rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), | |
| (char **)GVTOP(ArgValues[1]))); | |
| return rv; | |
| } | |
| break; | |
| case 1: | |
| if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) { | |
| GenericValue rv; | |
| int (*PF)(int) = (int (*)(int))(intptr_t)FPtr; | |
| rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); | |
| return rv; | |
| } | |
| break; | |
| } | |
| } | |
| // Handle cases where no arguments are passed first. | |
| if (ArgValues.empty()) { | |
| GenericValue rv; | |
| switch (RetTy->getTypeID()) { | |
| default: | |
| llvm_unreachable("Unknown return type for function call!"); | |
| case Type::IntegerTyID: { | |
| unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); | |
| if (BitWidth == 1) | |
| rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)()); | |
| else if (BitWidth <= 8) | |
| rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)()); | |
| else if (BitWidth <= 16) | |
| rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)()); | |
| else if (BitWidth <= 32) | |
| rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)()); | |
| else if (BitWidth <= 64) | |
| rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)()); | |
| else | |
| llvm_unreachable("Integer types > 64 bits not supported"); | |
| return rv; | |
| } | |
| case Type::VoidTyID: | |
| rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)()); | |
| return rv; | |
| case Type::FloatTyID: | |
| rv.FloatVal = ((float (*)())(intptr_t)FPtr)(); | |
| return rv; | |
| case Type::DoubleTyID: | |
| rv.DoubleVal = ((double (*)())(intptr_t)FPtr)(); | |
| return rv; | |
| case Type::X86_FP80TyID: | |
| case Type::FP128TyID: | |
| case Type::PPC_FP128TyID: | |
| llvm_unreachable("long double not supported yet"); | |
| case Type::PointerTyID: | |
| return PTOGV(((void *(*)())(intptr_t)FPtr)()); | |
| } | |
| } | |
| llvm_unreachable("Full-featured argument passing not supported yet!"); | |
| } | |
| void OrcMCJITReplacement::runStaticConstructorsDestructors(bool isDtors) { | |
| auto &CtorDtorsMap = isDtors ? UnexecutedDestructors : UnexecutedConstructors; | |
| for (auto &KV : CtorDtorsMap) | |
| cantFail(CtorDtorRunner<LazyEmitLayerT>(std::move(KV.second), KV.first) | |
| .runViaLayer(LazyEmitLayer)); | |
| CtorDtorsMap.clear(); | |
| } | |
| } // End namespace orc. | |
| } // End namespace llvm. |