| //===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCJIT.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ExecutionEngine/GenericValue.h" |
| #include "llvm/ExecutionEngine/JITEventListener.h" |
| #include "llvm/ExecutionEngine/MCJIT.h" |
| #include "llvm/ExecutionEngine/SectionMemoryManager.h" |
| #include "llvm/IR/DataLayout.h" |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/LegacyPassManager.h" |
| #include "llvm/IR/Mangler.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Object/Archive.h" |
| #include "llvm/Object/ObjectFile.h" |
| #include "llvm/Support/DynamicLibrary.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/MutexGuard.h" |
| |
| using namespace llvm; |
| |
| namespace { |
| |
| static struct RegisterJIT { |
| RegisterJIT() { MCJIT::Register(); } |
| } JITRegistrator; |
| |
| } |
| |
| extern "C" void LLVMLinkInMCJIT() { |
| } |
| |
| ExecutionEngine * |
| MCJIT::createJIT(std::unique_ptr<Module> M, std::string *ErrorStr, |
| std::shared_ptr<MCJITMemoryManager> MemMgr, |
| std::shared_ptr<LegacyJITSymbolResolver> Resolver, |
| std::unique_ptr<TargetMachine> TM) { |
| // Try to register the program as a source of symbols to resolve against. |
| // |
| // FIXME: Don't do this here. |
| sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr); |
| |
| if (!MemMgr || !Resolver) { |
| auto RTDyldMM = std::make_shared<SectionMemoryManager>(); |
| if (!MemMgr) |
| MemMgr = RTDyldMM; |
| if (!Resolver) |
| Resolver = RTDyldMM; |
| } |
| |
| return new MCJIT(std::move(M), std::move(TM), std::move(MemMgr), |
| std::move(Resolver)); |
| } |
| |
| MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM, |
| std::shared_ptr<MCJITMemoryManager> MemMgr, |
| std::shared_ptr<LegacyJITSymbolResolver> Resolver) |
| : ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)), |
| Ctx(nullptr), MemMgr(std::move(MemMgr)), |
| Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver), |
| ObjCache(nullptr) { |
| // FIXME: We are managing our modules, so we do not want the base class |
| // ExecutionEngine to manage them as well. To avoid double destruction |
| // of the first (and only) module added in ExecutionEngine constructor |
| // we remove it from EE and will destruct it ourselves. |
| // |
| // It may make sense to move our module manager (based on SmallStPtr) back |
| // into EE if the JIT and Interpreter can live with it. |
| // If so, additional functions: addModule, removeModule, FindFunctionNamed, |
| // runStaticConstructorsDestructors could be moved back to EE as well. |
| // |
| std::unique_ptr<Module> First = std::move(Modules[0]); |
| Modules.clear(); |
| |
| if (First->getDataLayout().isDefault()) |
| First->setDataLayout(getDataLayout()); |
| |
| OwnedModules.addModule(std::move(First)); |
| RegisterJITEventListener(JITEventListener::createGDBRegistrationListener()); |
| } |
| |
| MCJIT::~MCJIT() { |
| MutexGuard locked(lock); |
| |
| Dyld.deregisterEHFrames(); |
| |
| for (auto &Obj : LoadedObjects) |
| if (Obj) |
| NotifyFreeingObject(*Obj); |
| |
| Archives.clear(); |
| } |
| |
| void MCJIT::addModule(std::unique_ptr<Module> M) { |
| MutexGuard locked(lock); |
| |
| if (M->getDataLayout().isDefault()) |
| M->setDataLayout(getDataLayout()); |
| |
| OwnedModules.addModule(std::move(M)); |
| } |
| |
| bool MCJIT::removeModule(Module *M) { |
| MutexGuard locked(lock); |
| return OwnedModules.removeModule(M); |
| } |
| |
| void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) { |
| std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(*Obj); |
| if (Dyld.hasError()) |
| report_fatal_error(Dyld.getErrorString()); |
| |
| NotifyObjectEmitted(*Obj, *L); |
| |
| LoadedObjects.push_back(std::move(Obj)); |
| } |
| |
| void MCJIT::addObjectFile(object::OwningBinary<object::ObjectFile> Obj) { |
| std::unique_ptr<object::ObjectFile> ObjFile; |
| std::unique_ptr<MemoryBuffer> MemBuf; |
| std::tie(ObjFile, MemBuf) = Obj.takeBinary(); |
| addObjectFile(std::move(ObjFile)); |
| Buffers.push_back(std::move(MemBuf)); |
| } |
| |
| void MCJIT::addArchive(object::OwningBinary<object::Archive> A) { |
| Archives.push_back(std::move(A)); |
| } |
| |
| void MCJIT::setObjectCache(ObjectCache* NewCache) { |
| MutexGuard locked(lock); |
| ObjCache = NewCache; |
| } |
| |
| std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) { |
| assert(M && "Can not emit a null module"); |
| |
| MutexGuard locked(lock); |
| |
| // Materialize all globals in the module if they have not been |
| // materialized already. |
| cantFail(M->materializeAll()); |
| |
| // This must be a module which has already been added but not loaded to this |
| // MCJIT instance, since these conditions are tested by our caller, |
| // generateCodeForModule. |
| |
| legacy::PassManager PM; |
| |
| // The RuntimeDyld will take ownership of this shortly |
| SmallVector<char, 4096> ObjBufferSV; |
| raw_svector_ostream ObjStream(ObjBufferSV); |
| |
| // Turn the machine code intermediate representation into bytes in memory |
| // that may be executed. |
| if (TM->addPassesToEmitMC(PM, Ctx, ObjStream, !getVerifyModules())) |
| report_fatal_error("Target does not support MC emission!"); |
| |
| // Initialize passes. |
| PM.run(*M); |
| // Flush the output buffer to get the generated code into memory |
| |
| std::unique_ptr<MemoryBuffer> CompiledObjBuffer( |
| new SmallVectorMemoryBuffer(std::move(ObjBufferSV))); |
| |
| // If we have an object cache, tell it about the new object. |
| // Note that we're using the compiled image, not the loaded image (as below). |
| if (ObjCache) { |
| // MemoryBuffer is a thin wrapper around the actual memory, so it's OK |
| // to create a temporary object here and delete it after the call. |
| MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef(); |
| ObjCache->notifyObjectCompiled(M, MB); |
| } |
| |
| return CompiledObjBuffer; |
| } |
| |
| void MCJIT::generateCodeForModule(Module *M) { |
| // Get a thread lock to make sure we aren't trying to load multiple times |
| MutexGuard locked(lock); |
| |
| // This must be a module which has already been added to this MCJIT instance. |
| assert(OwnedModules.ownsModule(M) && |
| "MCJIT::generateCodeForModule: Unknown module."); |
| |
| // Re-compilation is not supported |
| if (OwnedModules.hasModuleBeenLoaded(M)) |
| return; |
| |
| std::unique_ptr<MemoryBuffer> ObjectToLoad; |
| // Try to load the pre-compiled object from cache if possible |
| if (ObjCache) |
| ObjectToLoad = ObjCache->getObject(M); |
| |
| assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch"); |
| |
| // If the cache did not contain a suitable object, compile the object |
| if (!ObjectToLoad) { |
| ObjectToLoad = emitObject(M); |
| assert(ObjectToLoad && "Compilation did not produce an object."); |
| } |
| |
| // Load the object into the dynamic linker. |
| // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list). |
| Expected<std::unique_ptr<object::ObjectFile>> LoadedObject = |
| object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef()); |
| if (!LoadedObject) { |
| std::string Buf; |
| raw_string_ostream OS(Buf); |
| logAllUnhandledErrors(LoadedObject.takeError(), OS, ""); |
| OS.flush(); |
| report_fatal_error(Buf); |
| } |
| std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = |
| Dyld.loadObject(*LoadedObject.get()); |
| |
| if (Dyld.hasError()) |
| report_fatal_error(Dyld.getErrorString()); |
| |
| NotifyObjectEmitted(*LoadedObject.get(), *L); |
| |
| Buffers.push_back(std::move(ObjectToLoad)); |
| LoadedObjects.push_back(std::move(*LoadedObject)); |
| |
| OwnedModules.markModuleAsLoaded(M); |
| } |
| |
| void MCJIT::finalizeLoadedModules() { |
| MutexGuard locked(lock); |
| |
| // Resolve any outstanding relocations. |
| Dyld.resolveRelocations(); |
| |
| OwnedModules.markAllLoadedModulesAsFinalized(); |
| |
| // Register EH frame data for any module we own which has been loaded |
| Dyld.registerEHFrames(); |
| |
| // Set page permissions. |
| MemMgr->finalizeMemory(); |
| } |
| |
| // FIXME: Rename this. |
| void MCJIT::finalizeObject() { |
| MutexGuard locked(lock); |
| |
| // Generate code for module is going to move objects out of the 'added' list, |
| // so we need to copy that out before using it: |
| SmallVector<Module*, 16> ModsToAdd; |
| for (auto M : OwnedModules.added()) |
| ModsToAdd.push_back(M); |
| |
| for (auto M : ModsToAdd) |
| generateCodeForModule(M); |
| |
| finalizeLoadedModules(); |
| } |
| |
| void MCJIT::finalizeModule(Module *M) { |
| MutexGuard locked(lock); |
| |
| // This must be a module which has already been added to this MCJIT instance. |
| assert(OwnedModules.ownsModule(M) && "MCJIT::finalizeModule: Unknown module."); |
| |
| // If the module hasn't been compiled, just do that. |
| if (!OwnedModules.hasModuleBeenLoaded(M)) |
| generateCodeForModule(M); |
| |
| finalizeLoadedModules(); |
| } |
| |
| JITSymbol MCJIT::findExistingSymbol(const std::string &Name) { |
| if (void *Addr = getPointerToGlobalIfAvailable(Name)) |
| return JITSymbol(static_cast<uint64_t>( |
| reinterpret_cast<uintptr_t>(Addr)), |
| JITSymbolFlags::Exported); |
| |
| return Dyld.getSymbol(Name); |
| } |
| |
| Module *MCJIT::findModuleForSymbol(const std::string &Name, |
| bool CheckFunctionsOnly) { |
| StringRef DemangledName = Name; |
| if (DemangledName[0] == getDataLayout().getGlobalPrefix()) |
| DemangledName = DemangledName.substr(1); |
| |
| MutexGuard locked(lock); |
| |
| // If it hasn't already been generated, see if it's in one of our modules. |
| for (ModulePtrSet::iterator I = OwnedModules.begin_added(), |
| E = OwnedModules.end_added(); |
| I != E; ++I) { |
| Module *M = *I; |
| Function *F = M->getFunction(DemangledName); |
| if (F && !F->isDeclaration()) |
| return M; |
| if (!CheckFunctionsOnly) { |
| GlobalVariable *G = M->getGlobalVariable(DemangledName); |
| if (G && !G->isDeclaration()) |
| return M; |
| // FIXME: Do we need to worry about global aliases? |
| } |
| } |
| // We didn't find the symbol in any of our modules. |
| return nullptr; |
| } |
| |
| uint64_t MCJIT::getSymbolAddress(const std::string &Name, |
| bool CheckFunctionsOnly) { |
| std::string MangledName; |
| { |
| raw_string_ostream MangledNameStream(MangledName); |
| Mangler::getNameWithPrefix(MangledNameStream, Name, getDataLayout()); |
| } |
| if (auto Sym = findSymbol(MangledName, CheckFunctionsOnly)) { |
| if (auto AddrOrErr = Sym.getAddress()) |
| return *AddrOrErr; |
| else |
| report_fatal_error(AddrOrErr.takeError()); |
| } else |
| report_fatal_error(Sym.takeError()); |
| } |
| |
| JITSymbol MCJIT::findSymbol(const std::string &Name, |
| bool CheckFunctionsOnly) { |
| MutexGuard locked(lock); |
| |
| // First, check to see if we already have this symbol. |
| if (auto Sym = findExistingSymbol(Name)) |
| return Sym; |
| |
| for (object::OwningBinary<object::Archive> &OB : Archives) { |
| object::Archive *A = OB.getBinary(); |
| // Look for our symbols in each Archive |
| auto OptionalChildOrErr = A->findSym(Name); |
| if (!OptionalChildOrErr) |
| report_fatal_error(OptionalChildOrErr.takeError()); |
| auto &OptionalChild = *OptionalChildOrErr; |
| if (OptionalChild) { |
| // FIXME: Support nested archives? |
| Expected<std::unique_ptr<object::Binary>> ChildBinOrErr = |
| OptionalChild->getAsBinary(); |
| if (!ChildBinOrErr) { |
| // TODO: Actually report errors helpfully. |
| consumeError(ChildBinOrErr.takeError()); |
| continue; |
| } |
| std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get(); |
| if (ChildBin->isObject()) { |
| std::unique_ptr<object::ObjectFile> OF( |
| static_cast<object::ObjectFile *>(ChildBin.release())); |
| // This causes the object file to be loaded. |
| addObjectFile(std::move(OF)); |
| // The address should be here now. |
| if (auto Sym = findExistingSymbol(Name)) |
| return Sym; |
| } |
| } |
| } |
| |
| // If it hasn't already been generated, see if it's in one of our modules. |
| Module *M = findModuleForSymbol(Name, CheckFunctionsOnly); |
| if (M) { |
| generateCodeForModule(M); |
| |
| // Check the RuntimeDyld table again, it should be there now. |
| return findExistingSymbol(Name); |
| } |
| |
| // If a LazyFunctionCreator is installed, use it to get/create the function. |
| // FIXME: Should we instead have a LazySymbolCreator callback? |
| if (LazyFunctionCreator) { |
| auto Addr = static_cast<uint64_t>( |
| reinterpret_cast<uintptr_t>(LazyFunctionCreator(Name))); |
| return JITSymbol(Addr, JITSymbolFlags::Exported); |
| } |
| |
| return nullptr; |
| } |
| |
| uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) { |
| MutexGuard locked(lock); |
| uint64_t Result = getSymbolAddress(Name, false); |
| if (Result != 0) |
| finalizeLoadedModules(); |
| return Result; |
| } |
| |
| uint64_t MCJIT::getFunctionAddress(const std::string &Name) { |
| MutexGuard locked(lock); |
| uint64_t Result = getSymbolAddress(Name, true); |
| if (Result != 0) |
| finalizeLoadedModules(); |
| return Result; |
| } |
| |
| // Deprecated. Use getFunctionAddress instead. |
| void *MCJIT::getPointerToFunction(Function *F) { |
| MutexGuard locked(lock); |
| |
| Mangler Mang; |
| SmallString<128> Name; |
| TM->getNameWithPrefix(Name, F, Mang); |
| |
| if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { |
| bool AbortOnFailure = !F->hasExternalWeakLinkage(); |
| void *Addr = getPointerToNamedFunction(Name, AbortOnFailure); |
| updateGlobalMapping(F, Addr); |
| return Addr; |
| } |
| |
| Module *M = F->getParent(); |
| bool HasBeenAddedButNotLoaded = OwnedModules.hasModuleBeenAddedButNotLoaded(M); |
| |
| // Make sure the relevant module has been compiled and loaded. |
| if (HasBeenAddedButNotLoaded) |
| generateCodeForModule(M); |
| else if (!OwnedModules.hasModuleBeenLoaded(M)) { |
| // If this function doesn't belong to one of our modules, we're done. |
| // FIXME: Asking for the pointer to a function that hasn't been registered, |
| // and isn't a declaration (which is handled above) should probably |
| // be an assertion. |
| return nullptr; |
| } |
| |
| // FIXME: Should the Dyld be retaining module information? Probably not. |
| // |
| // This is the accessor for the target address, so make sure to check the |
| // load address of the symbol, not the local address. |
| return (void*)Dyld.getSymbol(Name).getAddress(); |
| } |
| |
| void MCJIT::runStaticConstructorsDestructorsInModulePtrSet( |
| bool isDtors, ModulePtrSet::iterator I, ModulePtrSet::iterator E) { |
| for (; I != E; ++I) { |
| ExecutionEngine::runStaticConstructorsDestructors(**I, isDtors); |
| } |
| } |
| |
| void MCJIT::runStaticConstructorsDestructors(bool isDtors) { |
| // Execute global ctors/dtors for each module in the program. |
| runStaticConstructorsDestructorsInModulePtrSet( |
| isDtors, OwnedModules.begin_added(), OwnedModules.end_added()); |
| runStaticConstructorsDestructorsInModulePtrSet( |
| isDtors, OwnedModules.begin_loaded(), OwnedModules.end_loaded()); |
| runStaticConstructorsDestructorsInModulePtrSet( |
| isDtors, OwnedModules.begin_finalized(), OwnedModules.end_finalized()); |
| } |
| |
| Function *MCJIT::FindFunctionNamedInModulePtrSet(StringRef FnName, |
| ModulePtrSet::iterator I, |
| ModulePtrSet::iterator E) { |
| for (; I != E; ++I) { |
| Function *F = (*I)->getFunction(FnName); |
| if (F && !F->isDeclaration()) |
| return F; |
| } |
| return nullptr; |
| } |
| |
| GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(StringRef Name, |
| bool AllowInternal, |
| ModulePtrSet::iterator I, |
| ModulePtrSet::iterator E) { |
| for (; I != E; ++I) { |
| GlobalVariable *GV = (*I)->getGlobalVariable(Name, AllowInternal); |
| if (GV && !GV->isDeclaration()) |
| return GV; |
| } |
| return nullptr; |
| } |
| |
| |
| Function *MCJIT::FindFunctionNamed(StringRef FnName) { |
| Function *F = FindFunctionNamedInModulePtrSet( |
| FnName, OwnedModules.begin_added(), OwnedModules.end_added()); |
| if (!F) |
| F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_loaded(), |
| OwnedModules.end_loaded()); |
| if (!F) |
| F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_finalized(), |
| OwnedModules.end_finalized()); |
| return F; |
| } |
| |
| GlobalVariable *MCJIT::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) { |
| GlobalVariable *GV = FindGlobalVariableNamedInModulePtrSet( |
| Name, AllowInternal, OwnedModules.begin_added(), OwnedModules.end_added()); |
| if (!GV) |
| GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_loaded(), |
| OwnedModules.end_loaded()); |
| if (!GV) |
| GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_finalized(), |
| OwnedModules.end_finalized()); |
| return GV; |
| } |
| |
| GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) { |
| assert(F && "Function *F was null at entry to run()"); |
| |
| void *FPtr = getPointerToFunction(F); |
| finalizeModule(F->getParent()); |
| 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)()); |
| } |
| } |
| |
| report_fatal_error("MCJIT::runFunction does not support full-featured " |
| "argument passing. Please use " |
| "ExecutionEngine::getFunctionAddress and cast the result " |
| "to the desired function pointer type."); |
| } |
| |
| void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) { |
| if (!isSymbolSearchingDisabled()) { |
| if (auto Sym = Resolver.findSymbol(Name)) { |
| if (auto AddrOrErr = Sym.getAddress()) |
| return reinterpret_cast<void*>( |
| static_cast<uintptr_t>(*AddrOrErr)); |
| } else if (auto Err = Sym.takeError()) |
| report_fatal_error(std::move(Err)); |
| } |
| |
| /// If a LazyFunctionCreator is installed, use it to get/create the function. |
| if (LazyFunctionCreator) |
| if (void *RP = LazyFunctionCreator(Name)) |
| return RP; |
| |
| if (AbortOnFailure) { |
| report_fatal_error("Program used external function '"+Name+ |
| "' which could not be resolved!"); |
| } |
| return nullptr; |
| } |
| |
| void MCJIT::RegisterJITEventListener(JITEventListener *L) { |
| if (!L) |
| return; |
| MutexGuard locked(lock); |
| EventListeners.push_back(L); |
| } |
| |
| void MCJIT::UnregisterJITEventListener(JITEventListener *L) { |
| if (!L) |
| return; |
| MutexGuard locked(lock); |
| auto I = find(reverse(EventListeners), L); |
| if (I != EventListeners.rend()) { |
| std::swap(*I, EventListeners.back()); |
| EventListeners.pop_back(); |
| } |
| } |
| |
| void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj, |
| const RuntimeDyld::LoadedObjectInfo &L) { |
| MutexGuard locked(lock); |
| MemMgr->notifyObjectLoaded(this, Obj); |
| for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { |
| EventListeners[I]->NotifyObjectEmitted(Obj, L); |
| } |
| } |
| |
| void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { |
| MutexGuard locked(lock); |
| for (JITEventListener *L : EventListeners) |
| L->NotifyFreeingObject(Obj); |
| } |
| |
| JITSymbol |
| LinkingSymbolResolver::findSymbol(const std::string &Name) { |
| auto Result = ParentEngine.findSymbol(Name, false); |
| if (Result) |
| return Result; |
| if (ParentEngine.isSymbolSearchingDisabled()) |
| return nullptr; |
| return ClientResolver->findSymbol(Name); |
| } |
| |
| void LinkingSymbolResolver::anchor() {} |