| //===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #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(LegacyCtorDtorRunner<LazyEmitLayerT>( |
| AcknowledgeORCv1Deprecation, std::move(KV.second), KV.first) |
| .runViaLayer(LazyEmitLayer)); |
| |
| CtorDtorsMap.clear(); |
| } |
| |
| } // End namespace orc. |
| } // End namespace llvm. |