682 lines · cpp
1//===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCJIT.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ExecutionEngine/GenericValue.h"12#include "llvm/ExecutionEngine/JITEventListener.h"13#include "llvm/ExecutionEngine/MCJIT.h"14#include "llvm/ExecutionEngine/ObjectCache.h"15#include "llvm/ExecutionEngine/SectionMemoryManager.h"16#include "llvm/IR/DataLayout.h"17#include "llvm/IR/DerivedTypes.h"18#include "llvm/IR/Function.h"19#include "llvm/IR/LegacyPassManager.h"20#include "llvm/IR/Mangler.h"21#include "llvm/IR/Module.h"22#include "llvm/Object/Archive.h"23#include "llvm/Object/ObjectFile.h"24#include "llvm/Support/DynamicLibrary.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/Support/MemoryBuffer.h"27#include "llvm/Support/SmallVectorMemoryBuffer.h"28#include <mutex>29 30using namespace llvm;31 32namespace {33 34static struct RegisterJIT {35 RegisterJIT() { MCJIT::Register(); }36} JITRegistrator;37 38}39 40extern "C" void LLVMLinkInMCJIT() {41}42 43ExecutionEngine *44MCJIT::createJIT(std::unique_ptr<Module> M, std::string *ErrorStr,45 std::shared_ptr<MCJITMemoryManager> MemMgr,46 std::shared_ptr<LegacyJITSymbolResolver> Resolver,47 std::unique_ptr<TargetMachine> TM) {48 // Try to register the program as a source of symbols to resolve against.49 //50 // FIXME: Don't do this here.51 sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr);52 53 if (!MemMgr || !Resolver) {54 auto RTDyldMM = std::make_shared<SectionMemoryManager>();55 if (!MemMgr)56 MemMgr = RTDyldMM;57 if (!Resolver)58 Resolver = RTDyldMM;59 }60 61 return new MCJIT(std::move(M), std::move(TM), std::move(MemMgr),62 std::move(Resolver));63}64 65MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM,66 std::shared_ptr<MCJITMemoryManager> MemMgr,67 std::shared_ptr<LegacyJITSymbolResolver> Resolver)68 : ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)),69 Ctx(nullptr), MemMgr(std::move(MemMgr)),70 Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver),71 ObjCache(nullptr) {72 // FIXME: We are managing our modules, so we do not want the base class73 // ExecutionEngine to manage them as well. To avoid double destruction74 // of the first (and only) module added in ExecutionEngine constructor75 // we remove it from EE and will destruct it ourselves.76 //77 // It may make sense to move our module manager (based on SmallStPtr) back78 // into EE if the JIT and Interpreter can live with it.79 // If so, additional functions: addModule, removeModule, FindFunctionNamed,80 // runStaticConstructorsDestructors could be moved back to EE as well.81 //82 std::unique_ptr<Module> First = std::move(Modules[0]);83 Modules.clear();84 85 if (First->getDataLayout().isDefault())86 First->setDataLayout(getDataLayout());87 88 OwnedModules.addModule(std::move(First));89 RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());90}91 92MCJIT::~MCJIT() {93 std::lock_guard<sys::Mutex> locked(lock);94 95 Dyld.deregisterEHFrames();96 97 for (auto &Obj : LoadedObjects)98 if (Obj)99 notifyFreeingObject(*Obj);100 101 Archives.clear();102}103 104void MCJIT::addModule(std::unique_ptr<Module> M) {105 std::lock_guard<sys::Mutex> locked(lock);106 107 if (M->getDataLayout().isDefault())108 M->setDataLayout(getDataLayout());109 110 OwnedModules.addModule(std::move(M));111}112 113bool MCJIT::removeModule(Module *M) {114 std::lock_guard<sys::Mutex> locked(lock);115 return OwnedModules.removeModule(M);116}117 118void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) {119 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(*Obj);120 if (Dyld.hasError())121 report_fatal_error(Dyld.getErrorString());122 123 notifyObjectLoaded(*Obj, *L);124 125 LoadedObjects.push_back(std::move(Obj));126}127 128void MCJIT::addObjectFile(object::OwningBinary<object::ObjectFile> Obj) {129 std::unique_ptr<object::ObjectFile> ObjFile;130 std::unique_ptr<MemoryBuffer> MemBuf;131 std::tie(ObjFile, MemBuf) = Obj.takeBinary();132 addObjectFile(std::move(ObjFile));133 Buffers.push_back(std::move(MemBuf));134}135 136void MCJIT::addArchive(object::OwningBinary<object::Archive> A) {137 Archives.push_back(std::move(A));138}139 140void MCJIT::setObjectCache(ObjectCache* NewCache) {141 std::lock_guard<sys::Mutex> locked(lock);142 ObjCache = NewCache;143}144 145std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) {146 assert(M && "Can not emit a null module");147 148 std::lock_guard<sys::Mutex> locked(lock);149 150 // Materialize all globals in the module if they have not been151 // materialized already.152 cantFail(M->materializeAll());153 154 // This must be a module which has already been added but not loaded to this155 // MCJIT instance, since these conditions are tested by our caller,156 // generateCodeForModule.157 158 legacy::PassManager PM;159 160 // The RuntimeDyld will take ownership of this shortly161 SmallVector<char, 4096> ObjBufferSV;162 raw_svector_ostream ObjStream(ObjBufferSV);163 164 // Turn the machine code intermediate representation into bytes in memory165 // that may be executed.166 if (TM->addPassesToEmitMC(PM, Ctx, ObjStream, !getVerifyModules()))167 report_fatal_error("Target does not support MC emission!");168 169 // Initialize passes.170 PM.run(*M);171 // Flush the output buffer to get the generated code into memory172 173 auto CompiledObjBuffer = std::make_unique<SmallVectorMemoryBuffer>(174 std::move(ObjBufferSV), /*RequiresNullTerminator=*/false);175 176 // If we have an object cache, tell it about the new object.177 // Note that we're using the compiled image, not the loaded image (as below).178 if (ObjCache) {179 // MemoryBuffer is a thin wrapper around the actual memory, so it's OK180 // to create a temporary object here and delete it after the call.181 MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef();182 ObjCache->notifyObjectCompiled(M, MB);183 }184 185 return CompiledObjBuffer;186}187 188void MCJIT::generateCodeForModule(Module *M) {189 // Get a thread lock to make sure we aren't trying to load multiple times190 std::lock_guard<sys::Mutex> locked(lock);191 192 // This must be a module which has already been added to this MCJIT instance.193 assert(OwnedModules.ownsModule(M) &&194 "MCJIT::generateCodeForModule: Unknown module.");195 196 // Re-compilation is not supported197 if (OwnedModules.hasModuleBeenLoaded(M))198 return;199 200 std::unique_ptr<MemoryBuffer> ObjectToLoad;201 // Try to load the pre-compiled object from cache if possible202 if (ObjCache)203 ObjectToLoad = ObjCache->getObject(M);204 205 assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");206 207 // If the cache did not contain a suitable object, compile the object208 if (!ObjectToLoad) {209 ObjectToLoad = emitObject(M);210 assert(ObjectToLoad && "Compilation did not produce an object.");211 }212 213 // Load the object into the dynamic linker.214 // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list).215 Expected<std::unique_ptr<object::ObjectFile>> LoadedObject =216 object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef());217 if (!LoadedObject) {218 std::string Buf;219 raw_string_ostream OS(Buf);220 logAllUnhandledErrors(LoadedObject.takeError(), OS);221 report_fatal_error(Twine(Buf));222 }223 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L =224 Dyld.loadObject(*LoadedObject.get());225 226 if (Dyld.hasError())227 report_fatal_error(Dyld.getErrorString());228 229 notifyObjectLoaded(*LoadedObject.get(), *L);230 231 Buffers.push_back(std::move(ObjectToLoad));232 LoadedObjects.push_back(std::move(*LoadedObject));233 234 OwnedModules.markModuleAsLoaded(M);235}236 237void MCJIT::finalizeLoadedModules() {238 std::lock_guard<sys::Mutex> locked(lock);239 240 // Resolve any outstanding relocations.241 Dyld.resolveRelocations();242 243 // Check for Dyld error.244 if (Dyld.hasError())245 ErrMsg = Dyld.getErrorString().str();246 247 OwnedModules.markAllLoadedModulesAsFinalized();248 249 // Register EH frame data for any module we own which has been loaded250 Dyld.registerEHFrames();251 252 // Set page permissions.253 MemMgr->finalizeMemory();254}255 256// FIXME: Rename this.257void MCJIT::finalizeObject() {258 std::lock_guard<sys::Mutex> locked(lock);259 260 // Generate code for module is going to move objects out of the 'added' list,261 // so we need to copy that out before using it:262 SmallVector<Module *, 16> ModsToAdd(OwnedModules.added());263 264 for (auto *M : ModsToAdd)265 generateCodeForModule(M);266 267 finalizeLoadedModules();268}269 270void MCJIT::finalizeModule(Module *M) {271 std::lock_guard<sys::Mutex> locked(lock);272 273 // This must be a module which has already been added to this MCJIT instance.274 assert(OwnedModules.ownsModule(M) && "MCJIT::finalizeModule: Unknown module.");275 276 // If the module hasn't been compiled, just do that.277 if (!OwnedModules.hasModuleBeenLoaded(M))278 generateCodeForModule(M);279 280 finalizeLoadedModules();281}282 283JITSymbol MCJIT::findExistingSymbol(const std::string &Name) {284 if (void *Addr = getPointerToGlobalIfAvailable(Name))285 return JITSymbol(static_cast<uint64_t>(286 reinterpret_cast<uintptr_t>(Addr)),287 JITSymbolFlags::Exported);288 289 return Dyld.getSymbol(Name);290}291 292Module *MCJIT::findModuleForSymbol(const std::string &Name,293 bool CheckFunctionsOnly) {294 StringRef DemangledName = Name;295 if (DemangledName[0] == getDataLayout().getGlobalPrefix())296 DemangledName = DemangledName.substr(1);297 298 std::lock_guard<sys::Mutex> locked(lock);299 300 // If it hasn't already been generated, see if it's in one of our modules.301 for (ModulePtrSet::iterator I = OwnedModules.begin_added(),302 E = OwnedModules.end_added();303 I != E; ++I) {304 Module *M = *I;305 Function *F = M->getFunction(DemangledName);306 if (F && !F->isDeclaration())307 return M;308 if (!CheckFunctionsOnly) {309 GlobalVariable *G = M->getGlobalVariable(DemangledName);310 if (G && !G->isDeclaration())311 return M;312 // FIXME: Do we need to worry about global aliases?313 }314 }315 // We didn't find the symbol in any of our modules.316 return nullptr;317}318 319uint64_t MCJIT::getSymbolAddress(const std::string &Name,320 bool CheckFunctionsOnly) {321 std::string MangledName;322 {323 raw_string_ostream MangledNameStream(MangledName);324 Mangler::getNameWithPrefix(MangledNameStream, Name, getDataLayout());325 }326 if (auto Sym = findSymbol(MangledName, CheckFunctionsOnly)) {327 if (auto AddrOrErr = Sym.getAddress())328 return *AddrOrErr;329 else330 report_fatal_error(AddrOrErr.takeError());331 } else if (auto Err = Sym.takeError())332 report_fatal_error(Sym.takeError());333 return 0;334}335 336JITSymbol MCJIT::findSymbol(const std::string &Name,337 bool CheckFunctionsOnly) {338 std::lock_guard<sys::Mutex> locked(lock);339 340 // First, check to see if we already have this symbol.341 if (auto Sym = findExistingSymbol(Name))342 return Sym;343 344 for (object::OwningBinary<object::Archive> &OB : Archives) {345 object::Archive *A = OB.getBinary();346 // Look for our symbols in each Archive347 auto OptionalChildOrErr = A->findSym(Name);348 if (!OptionalChildOrErr)349 report_fatal_error(OptionalChildOrErr.takeError());350 auto &OptionalChild = *OptionalChildOrErr;351 if (OptionalChild) {352 // FIXME: Support nested archives?353 Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =354 OptionalChild->getAsBinary();355 if (!ChildBinOrErr) {356 // TODO: Actually report errors helpfully.357 consumeError(ChildBinOrErr.takeError());358 continue;359 }360 std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();361 if (ChildBin->isObject()) {362 std::unique_ptr<object::ObjectFile> OF(363 static_cast<object::ObjectFile *>(ChildBin.release()));364 // This causes the object file to be loaded.365 addObjectFile(std::move(OF));366 // The address should be here now.367 if (auto Sym = findExistingSymbol(Name))368 return Sym;369 }370 }371 }372 373 // If it hasn't already been generated, see if it's in one of our modules.374 Module *M = findModuleForSymbol(Name, CheckFunctionsOnly);375 if (M) {376 generateCodeForModule(M);377 378 // Check the RuntimeDyld table again, it should be there now.379 return findExistingSymbol(Name);380 }381 382 // If a LazyFunctionCreator is installed, use it to get/create the function.383 // FIXME: Should we instead have a LazySymbolCreator callback?384 if (LazyFunctionCreator) {385 auto Addr = static_cast<uint64_t>(386 reinterpret_cast<uintptr_t>(LazyFunctionCreator(Name)));387 return JITSymbol(Addr, JITSymbolFlags::Exported);388 }389 390 return nullptr;391}392 393uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) {394 std::lock_guard<sys::Mutex> locked(lock);395 uint64_t Result = getSymbolAddress(Name, false);396 if (Result != 0)397 finalizeLoadedModules();398 return Result;399}400 401uint64_t MCJIT::getFunctionAddress(const std::string &Name) {402 std::lock_guard<sys::Mutex> locked(lock);403 uint64_t Result = getSymbolAddress(Name, true);404 if (Result != 0)405 finalizeLoadedModules();406 return Result;407}408 409// Deprecated. Use getFunctionAddress instead.410void *MCJIT::getPointerToFunction(Function *F) {411 std::lock_guard<sys::Mutex> locked(lock);412 413 Mangler Mang;414 SmallString<128> Name;415 TM->getNameWithPrefix(Name, F, Mang);416 417 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {418 bool AbortOnFailure = !F->hasExternalWeakLinkage();419 void *Addr = getPointerToNamedFunction(Name, AbortOnFailure);420 updateGlobalMapping(F, Addr);421 return Addr;422 }423 424 Module *M = F->getParent();425 bool HasBeenAddedButNotLoaded = OwnedModules.hasModuleBeenAddedButNotLoaded(M);426 427 // Make sure the relevant module has been compiled and loaded.428 if (HasBeenAddedButNotLoaded)429 generateCodeForModule(M);430 else if (!OwnedModules.hasModuleBeenLoaded(M)) {431 // If this function doesn't belong to one of our modules, we're done.432 // FIXME: Asking for the pointer to a function that hasn't been registered,433 // and isn't a declaration (which is handled above) should probably434 // be an assertion.435 return nullptr;436 }437 438 // FIXME: Should the Dyld be retaining module information? Probably not.439 //440 // This is the accessor for the target address, so make sure to check the441 // load address of the symbol, not the local address.442 return (void*)Dyld.getSymbol(Name).getAddress();443}444 445void MCJIT::runStaticConstructorsDestructorsInModulePtrSet(446 bool isDtors, ModulePtrSet::iterator I, ModulePtrSet::iterator E) {447 for (; I != E; ++I) {448 ExecutionEngine::runStaticConstructorsDestructors(**I, isDtors);449 }450}451 452void MCJIT::runStaticConstructorsDestructors(bool isDtors) {453 // Execute global ctors/dtors for each module in the program.454 runStaticConstructorsDestructorsInModulePtrSet(455 isDtors, OwnedModules.begin_added(), OwnedModules.end_added());456 runStaticConstructorsDestructorsInModulePtrSet(457 isDtors, OwnedModules.begin_loaded(), OwnedModules.end_loaded());458 runStaticConstructorsDestructorsInModulePtrSet(459 isDtors, OwnedModules.begin_finalized(), OwnedModules.end_finalized());460}461 462Function *MCJIT::FindFunctionNamedInModulePtrSet(StringRef FnName,463 ModulePtrSet::iterator I,464 ModulePtrSet::iterator E) {465 for (; I != E; ++I) {466 Function *F = (*I)->getFunction(FnName);467 if (F && !F->isDeclaration())468 return F;469 }470 return nullptr;471}472 473GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(StringRef Name,474 bool AllowInternal,475 ModulePtrSet::iterator I,476 ModulePtrSet::iterator E) {477 for (; I != E; ++I) {478 GlobalVariable *GV = (*I)->getGlobalVariable(Name, AllowInternal);479 if (GV && !GV->isDeclaration())480 return GV;481 }482 return nullptr;483}484 485 486Function *MCJIT::FindFunctionNamed(StringRef FnName) {487 Function *F = FindFunctionNamedInModulePtrSet(488 FnName, OwnedModules.begin_added(), OwnedModules.end_added());489 if (!F)490 F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_loaded(),491 OwnedModules.end_loaded());492 if (!F)493 F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_finalized(),494 OwnedModules.end_finalized());495 return F;496}497 498GlobalVariable *MCJIT::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) {499 GlobalVariable *GV = FindGlobalVariableNamedInModulePtrSet(500 Name, AllowInternal, OwnedModules.begin_added(), OwnedModules.end_added());501 if (!GV)502 GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_loaded(),503 OwnedModules.end_loaded());504 if (!GV)505 GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_finalized(),506 OwnedModules.end_finalized());507 return GV;508}509 510GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) {511 assert(F && "Function *F was null at entry to run()");512 513 void *FPtr = getPointerToFunction(F);514 finalizeModule(F->getParent());515 assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");516 FunctionType *FTy = F->getFunctionType();517 Type *RetTy = FTy->getReturnType();518 519 assert((FTy->getNumParams() == ArgValues.size() ||520 (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&521 "Wrong number of arguments passed into function!");522 assert(FTy->getNumParams() == ArgValues.size() &&523 "This doesn't support passing arguments through varargs (yet)!");524 525 // Handle some common cases first. These cases correspond to common `main'526 // prototypes.527 if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {528 switch (ArgValues.size()) {529 case 3:530 if (FTy->getParamType(0)->isIntegerTy(32) &&531 FTy->getParamType(1)->isPointerTy() &&532 FTy->getParamType(2)->isPointerTy()) {533 int (*PF)(int, char **, const char **) =534 (int(*)(int, char **, const char **))(intptr_t)FPtr;535 536 // Call the function.537 GenericValue rv;538 rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),539 (char **)GVTOP(ArgValues[1]),540 (const char **)GVTOP(ArgValues[2])));541 return rv;542 }543 break;544 case 2:545 if (FTy->getParamType(0)->isIntegerTy(32) &&546 FTy->getParamType(1)->isPointerTy()) {547 int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;548 549 // Call the function.550 GenericValue rv;551 rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),552 (char **)GVTOP(ArgValues[1])));553 return rv;554 }555 break;556 case 1:557 if (FTy->getNumParams() == 1 &&558 FTy->getParamType(0)->isIntegerTy(32)) {559 GenericValue rv;560 int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;561 rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));562 return rv;563 }564 break;565 }566 }567 568 // Handle cases where no arguments are passed first.569 if (ArgValues.empty()) {570 GenericValue rv;571 switch (RetTy->getTypeID()) {572 default: llvm_unreachable("Unknown return type for function call!");573 case Type::IntegerTyID: {574 unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();575 if (BitWidth == 1)576 rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());577 else if (BitWidth <= 8)578 rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());579 else if (BitWidth <= 16)580 rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());581 else if (BitWidth <= 32)582 rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());583 else if (BitWidth <= 64)584 rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());585 else586 llvm_unreachable("Integer types > 64 bits not supported");587 return rv;588 }589 case Type::VoidTyID:590 rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)(), true);591 return rv;592 case Type::FloatTyID:593 rv.FloatVal = ((float(*)())(intptr_t)FPtr)();594 return rv;595 case Type::DoubleTyID:596 rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();597 return rv;598 case Type::X86_FP80TyID:599 case Type::FP128TyID:600 case Type::PPC_FP128TyID:601 llvm_unreachable("long double not supported yet");602 case Type::PointerTyID:603 return PTOGV(((void*(*)())(intptr_t)FPtr)());604 }605 }606 607 report_fatal_error("MCJIT::runFunction does not support full-featured "608 "argument passing. Please use "609 "ExecutionEngine::getFunctionAddress and cast the result "610 "to the desired function pointer type.");611}612 613void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) {614 if (!isSymbolSearchingDisabled()) {615 if (auto Sym = Resolver.findSymbol(std::string(Name))) {616 if (auto AddrOrErr = Sym.getAddress())617 return reinterpret_cast<void*>(618 static_cast<uintptr_t>(*AddrOrErr));619 } else if (auto Err = Sym.takeError())620 report_fatal_error(std::move(Err));621 }622 623 /// If a LazyFunctionCreator is installed, use it to get/create the function.624 if (LazyFunctionCreator)625 if (void *RP = LazyFunctionCreator(std::string(Name)))626 return RP;627 628 if (AbortOnFailure) {629 report_fatal_error("Program used external function '"+Name+630 "' which could not be resolved!");631 }632 return nullptr;633}634 635void MCJIT::RegisterJITEventListener(JITEventListener *L) {636 if (!L)637 return;638 std::lock_guard<sys::Mutex> locked(lock);639 EventListeners.push_back(L);640}641 642void MCJIT::UnregisterJITEventListener(JITEventListener *L) {643 if (!L)644 return;645 std::lock_guard<sys::Mutex> locked(lock);646 auto I = find(reverse(EventListeners), L);647 if (I != EventListeners.rend()) {648 std::swap(*I, EventListeners.back());649 EventListeners.pop_back();650 }651}652 653void MCJIT::notifyObjectLoaded(const object::ObjectFile &Obj,654 const RuntimeDyld::LoadedObjectInfo &L) {655 uint64_t Key =656 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Obj.getData().data()));657 std::lock_guard<sys::Mutex> locked(lock);658 MemMgr->notifyObjectLoaded(this, Obj);659 for (JITEventListener *EL : EventListeners)660 EL->notifyObjectLoaded(Key, Obj, L);661}662 663void MCJIT::notifyFreeingObject(const object::ObjectFile &Obj) {664 uint64_t Key =665 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Obj.getData().data()));666 std::lock_guard<sys::Mutex> locked(lock);667 for (JITEventListener *L : EventListeners)668 L->notifyFreeingObject(Key);669}670 671JITSymbol672LinkingSymbolResolver::findSymbol(const std::string &Name) {673 auto Result = ParentEngine.findSymbol(Name, false);674 if (Result)675 return Result;676 if (ParentEngine.isSymbolSearchingDisabled())677 return nullptr;678 return ClientResolver->findSymbol(Name);679}680 681void LinkingSymbolResolver::anchor() {}682