|  | //===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===// | 
|  | // | 
|  | // 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 "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/ObjectCache.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/SmallVectorMemoryBuffer.h" | 
|  | #include <mutex> | 
|  |  | 
|  | 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() { | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  |  | 
|  | Dyld.deregisterEHFrames(); | 
|  |  | 
|  | for (auto &Obj : LoadedObjects) | 
|  | if (Obj) | 
|  | notifyFreeingObject(*Obj); | 
|  |  | 
|  | Archives.clear(); | 
|  | } | 
|  |  | 
|  | void MCJIT::addModule(std::unique_ptr<Module> M) { | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  |  | 
|  | if (M->getDataLayout().isDefault()) | 
|  | M->setDataLayout(getDataLayout()); | 
|  |  | 
|  | OwnedModules.addModule(std::move(M)); | 
|  | } | 
|  |  | 
|  | bool MCJIT::removeModule(Module *M) { | 
|  | std::lock_guard<sys::Mutex> 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()); | 
|  |  | 
|  | notifyObjectLoaded(*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) { | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | ObjCache = NewCache; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) { | 
|  | assert(M && "Can not emit a null module"); | 
|  |  | 
|  | std::lock_guard<sys::Mutex> 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 | 
|  |  | 
|  | auto CompiledObjBuffer = std::make_unique<SmallVectorMemoryBuffer>( | 
|  | std::move(ObjBufferSV), /*RequiresNullTerminator=*/false); | 
|  |  | 
|  | // 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 | 
|  | std::lock_guard<sys::Mutex> 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); | 
|  | report_fatal_error(Twine(Buf)); | 
|  | } | 
|  | std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = | 
|  | Dyld.loadObject(*LoadedObject.get()); | 
|  |  | 
|  | if (Dyld.hasError()) | 
|  | report_fatal_error(Dyld.getErrorString()); | 
|  |  | 
|  | notifyObjectLoaded(*LoadedObject.get(), *L); | 
|  |  | 
|  | Buffers.push_back(std::move(ObjectToLoad)); | 
|  | LoadedObjects.push_back(std::move(*LoadedObject)); | 
|  |  | 
|  | OwnedModules.markModuleAsLoaded(M); | 
|  | } | 
|  |  | 
|  | void MCJIT::finalizeLoadedModules() { | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  |  | 
|  | // Resolve any outstanding relocations. | 
|  | Dyld.resolveRelocations(); | 
|  |  | 
|  | // Check for Dyld error. | 
|  | if (Dyld.hasError()) | 
|  | ErrMsg = Dyld.getErrorString().str(); | 
|  |  | 
|  | 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() { | 
|  | std::lock_guard<sys::Mutex> 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(OwnedModules.added()); | 
|  |  | 
|  | for (auto *M : ModsToAdd) | 
|  | generateCodeForModule(M); | 
|  |  | 
|  | finalizeLoadedModules(); | 
|  | } | 
|  |  | 
|  | void MCJIT::finalizeModule(Module *M) { | 
|  | std::lock_guard<sys::Mutex> 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); | 
|  |  | 
|  | std::lock_guard<sys::Mutex> 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 if (auto Err = Sym.takeError()) | 
|  | report_fatal_error(Sym.takeError()); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | JITSymbol MCJIT::findSymbol(const std::string &Name, | 
|  | bool CheckFunctionsOnly) { | 
|  | std::lock_guard<sys::Mutex> 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) { | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | uint64_t Result = getSymbolAddress(Name, false); | 
|  | if (Result != 0) | 
|  | finalizeLoadedModules(); | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | uint64_t MCJIT::getFunctionAddress(const std::string &Name) { | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | uint64_t Result = getSymbolAddress(Name, true); | 
|  | if (Result != 0) | 
|  | finalizeLoadedModules(); | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | // Deprecated.  Use getFunctionAddress instead. | 
|  | void *MCJIT::getPointerToFunction(Function *F) { | 
|  | std::lock_guard<sys::Mutex> 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)(), true); | 
|  | 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(std::string(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(std::string(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; | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | EventListeners.push_back(L); | 
|  | } | 
|  |  | 
|  | void MCJIT::UnregisterJITEventListener(JITEventListener *L) { | 
|  | if (!L) | 
|  | return; | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | auto I = find(reverse(EventListeners), L); | 
|  | if (I != EventListeners.rend()) { | 
|  | std::swap(*I, EventListeners.back()); | 
|  | EventListeners.pop_back(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCJIT::notifyObjectLoaded(const object::ObjectFile &Obj, | 
|  | const RuntimeDyld::LoadedObjectInfo &L) { | 
|  | uint64_t Key = | 
|  | static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Obj.getData().data())); | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | MemMgr->notifyObjectLoaded(this, Obj); | 
|  | for (JITEventListener *EL : EventListeners) | 
|  | EL->notifyObjectLoaded(Key, Obj, L); | 
|  | } | 
|  |  | 
|  | void MCJIT::notifyFreeingObject(const object::ObjectFile &Obj) { | 
|  | uint64_t Key = | 
|  | static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Obj.getData().data())); | 
|  | std::lock_guard<sys::Mutex> locked(lock); | 
|  | for (JITEventListener *L : EventListeners) | 
|  | L->notifyFreeingObject(Key); | 
|  | } | 
|  |  | 
|  | 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() {} |