1 //===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
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"
34 static struct RegisterJIT
{
35 RegisterJIT() { MCJIT::Register(); }
40 extern "C" void LLVMLinkInMCJIT() {
44 MCJIT::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.
50 // FIXME: Don't do this here.
51 sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr);
53 if (!MemMgr
|| !Resolver
) {
54 auto RTDyldMM
= std::make_shared
<SectionMemoryManager
>();
61 return new MCJIT(std::move(M
), std::move(TM
), std::move(MemMgr
),
65 MCJIT::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
),
72 // FIXME: We are managing our modules, so we do not want the base class
73 // ExecutionEngine to manage them as well. To avoid double destruction
74 // of the first (and only) module added in ExecutionEngine constructor
75 // we remove it from EE and will destruct it ourselves.
77 // It may make sense to move our module manager (based on SmallStPtr) back
78 // 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.
82 std::unique_ptr
<Module
> First
= std::move(Modules
[0]);
85 if (First
->getDataLayout().isDefault())
86 First
->setDataLayout(getDataLayout());
88 OwnedModules
.addModule(std::move(First
));
89 RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
93 std::lock_guard
<sys::Mutex
> locked(lock
);
95 Dyld
.deregisterEHFrames();
97 for (auto &Obj
: LoadedObjects
)
99 notifyFreeingObject(*Obj
);
104 void MCJIT::addModule(std::unique_ptr
<Module
> M
) {
105 std::lock_guard
<sys::Mutex
> locked(lock
);
107 if (M
->getDataLayout().isDefault())
108 M
->setDataLayout(getDataLayout());
110 OwnedModules
.addModule(std::move(M
));
113 bool MCJIT::removeModule(Module
*M
) {
114 std::lock_guard
<sys::Mutex
> locked(lock
);
115 return OwnedModules
.removeModule(M
);
118 void MCJIT::addObjectFile(std::unique_ptr
<object::ObjectFile
> Obj
) {
119 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> L
= Dyld
.loadObject(*Obj
);
121 report_fatal_error(Dyld
.getErrorString());
123 notifyObjectLoaded(*Obj
, *L
);
125 LoadedObjects
.push_back(std::move(Obj
));
128 void 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
));
136 void MCJIT::addArchive(object::OwningBinary
<object::Archive
> A
) {
137 Archives
.push_back(std::move(A
));
140 void MCJIT::setObjectCache(ObjectCache
* NewCache
) {
141 std::lock_guard
<sys::Mutex
> locked(lock
);
145 std::unique_ptr
<MemoryBuffer
> MCJIT::emitObject(Module
*M
) {
146 assert(M
&& "Can not emit a null module");
148 std::lock_guard
<sys::Mutex
> locked(lock
);
150 // Materialize all globals in the module if they have not been
151 // materialized already.
152 cantFail(M
->materializeAll());
154 // This must be a module which has already been added but not loaded to this
155 // MCJIT instance, since these conditions are tested by our caller,
156 // generateCodeForModule.
158 legacy::PassManager PM
;
160 // The RuntimeDyld will take ownership of this shortly
161 SmallVector
<char, 4096> ObjBufferSV
;
162 raw_svector_ostream
ObjStream(ObjBufferSV
);
164 // Turn the machine code intermediate representation into bytes in memory
165 // that may be executed.
166 if (TM
->addPassesToEmitMC(PM
, Ctx
, ObjStream
, !getVerifyModules()))
167 report_fatal_error("Target does not support MC emission!");
169 // Initialize passes.
171 // Flush the output buffer to get the generated code into memory
173 auto CompiledObjBuffer
= std::make_unique
<SmallVectorMemoryBuffer
>(
174 std::move(ObjBufferSV
), /*RequiresNullTerminator=*/false);
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).
179 // MemoryBuffer is a thin wrapper around the actual memory, so it's OK
180 // to create a temporary object here and delete it after the call.
181 MemoryBufferRef MB
= CompiledObjBuffer
->getMemBufferRef();
182 ObjCache
->notifyObjectCompiled(M
, MB
);
185 return CompiledObjBuffer
;
188 void MCJIT::generateCodeForModule(Module
*M
) {
189 // Get a thread lock to make sure we aren't trying to load multiple times
190 std::lock_guard
<sys::Mutex
> locked(lock
);
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.");
196 // Re-compilation is not supported
197 if (OwnedModules
.hasModuleBeenLoaded(M
))
200 std::unique_ptr
<MemoryBuffer
> ObjectToLoad
;
201 // Try to load the pre-compiled object from cache if possible
203 ObjectToLoad
= ObjCache
->getObject(M
);
205 assert(M
->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
207 // If the cache did not contain a suitable object, compile the object
209 ObjectToLoad
= emitObject(M
);
210 assert(ObjectToLoad
&& "Compilation did not produce an object.");
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());
219 raw_string_ostream
OS(Buf
);
220 logAllUnhandledErrors(LoadedObject
.takeError(), OS
);
221 report_fatal_error(Twine(Buf
));
223 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> L
=
224 Dyld
.loadObject(*LoadedObject
.get());
227 report_fatal_error(Dyld
.getErrorString());
229 notifyObjectLoaded(*LoadedObject
.get(), *L
);
231 Buffers
.push_back(std::move(ObjectToLoad
));
232 LoadedObjects
.push_back(std::move(*LoadedObject
));
234 OwnedModules
.markModuleAsLoaded(M
);
237 void MCJIT::finalizeLoadedModules() {
238 std::lock_guard
<sys::Mutex
> locked(lock
);
240 // Resolve any outstanding relocations.
241 Dyld
.resolveRelocations();
243 // Check for Dyld error.
245 ErrMsg
= Dyld
.getErrorString().str();
247 OwnedModules
.markAllLoadedModulesAsFinalized();
249 // Register EH frame data for any module we own which has been loaded
250 Dyld
.registerEHFrames();
252 // Set page permissions.
253 MemMgr
->finalizeMemory();
256 // FIXME: Rename this.
257 void MCJIT::finalizeObject() {
258 std::lock_guard
<sys::Mutex
> locked(lock
);
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());
264 for (auto *M
: ModsToAdd
)
265 generateCodeForModule(M
);
267 finalizeLoadedModules();
270 void MCJIT::finalizeModule(Module
*M
) {
271 std::lock_guard
<sys::Mutex
> locked(lock
);
273 // This must be a module which has already been added to this MCJIT instance.
274 assert(OwnedModules
.ownsModule(M
) && "MCJIT::finalizeModule: Unknown module.");
276 // If the module hasn't been compiled, just do that.
277 if (!OwnedModules
.hasModuleBeenLoaded(M
))
278 generateCodeForModule(M
);
280 finalizeLoadedModules();
283 JITSymbol
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
);
289 return Dyld
.getSymbol(Name
);
292 Module
*MCJIT::findModuleForSymbol(const std::string
&Name
,
293 bool CheckFunctionsOnly
) {
294 StringRef DemangledName
= Name
;
295 if (DemangledName
[0] == getDataLayout().getGlobalPrefix())
296 DemangledName
= DemangledName
.substr(1);
298 std::lock_guard
<sys::Mutex
> locked(lock
);
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();
305 Function
*F
= M
->getFunction(DemangledName
);
306 if (F
&& !F
->isDeclaration())
308 if (!CheckFunctionsOnly
) {
309 GlobalVariable
*G
= M
->getGlobalVariable(DemangledName
);
310 if (G
&& !G
->isDeclaration())
312 // FIXME: Do we need to worry about global aliases?
315 // We didn't find the symbol in any of our modules.
319 uint64_t MCJIT::getSymbolAddress(const std::string
&Name
,
320 bool CheckFunctionsOnly
) {
321 std::string MangledName
;
323 raw_string_ostream
MangledNameStream(MangledName
);
324 Mangler::getNameWithPrefix(MangledNameStream
, Name
, getDataLayout());
326 if (auto Sym
= findSymbol(MangledName
, CheckFunctionsOnly
)) {
327 if (auto AddrOrErr
= Sym
.getAddress())
330 report_fatal_error(AddrOrErr
.takeError());
331 } else if (auto Err
= Sym
.takeError())
332 report_fatal_error(Sym
.takeError());
336 JITSymbol
MCJIT::findSymbol(const std::string
&Name
,
337 bool CheckFunctionsOnly
) {
338 std::lock_guard
<sys::Mutex
> locked(lock
);
340 // First, check to see if we already have this symbol.
341 if (auto Sym
= findExistingSymbol(Name
))
344 for (object::OwningBinary
<object::Archive
> &OB
: Archives
) {
345 object::Archive
*A
= OB
.getBinary();
346 // Look for our symbols in each Archive
347 auto OptionalChildOrErr
= A
->findSym(Name
);
348 if (!OptionalChildOrErr
)
349 report_fatal_error(OptionalChildOrErr
.takeError());
350 auto &OptionalChild
= *OptionalChildOrErr
;
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());
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
))
373 // If it hasn't already been generated, see if it's in one of our modules.
374 Module
*M
= findModuleForSymbol(Name
, CheckFunctionsOnly
);
376 generateCodeForModule(M
);
378 // Check the RuntimeDyld table again, it should be there now.
379 return findExistingSymbol(Name
);
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
);
393 uint64_t MCJIT::getGlobalValueAddress(const std::string
&Name
) {
394 std::lock_guard
<sys::Mutex
> locked(lock
);
395 uint64_t Result
= getSymbolAddress(Name
, false);
397 finalizeLoadedModules();
401 uint64_t MCJIT::getFunctionAddress(const std::string
&Name
) {
402 std::lock_guard
<sys::Mutex
> locked(lock
);
403 uint64_t Result
= getSymbolAddress(Name
, true);
405 finalizeLoadedModules();
409 // Deprecated. Use getFunctionAddress instead.
410 void *MCJIT::getPointerToFunction(Function
*F
) {
411 std::lock_guard
<sys::Mutex
> locked(lock
);
414 SmallString
<128> Name
;
415 TM
->getNameWithPrefix(Name
, F
, Mang
);
417 if (F
->isDeclaration() || F
->hasAvailableExternallyLinkage()) {
418 bool AbortOnFailure
= !F
->hasExternalWeakLinkage();
419 void *Addr
= getPointerToNamedFunction(Name
, AbortOnFailure
);
420 updateGlobalMapping(F
, Addr
);
424 Module
*M
= F
->getParent();
425 bool HasBeenAddedButNotLoaded
= OwnedModules
.hasModuleBeenAddedButNotLoaded(M
);
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 probably
438 // FIXME: Should the Dyld be retaining module information? Probably not.
440 // This is the accessor for the target address, so make sure to check the
441 // load address of the symbol, not the local address.
442 return (void*)Dyld
.getSymbol(Name
).getAddress();
445 void MCJIT::runStaticConstructorsDestructorsInModulePtrSet(
446 bool isDtors
, ModulePtrSet::iterator I
, ModulePtrSet::iterator E
) {
447 for (; I
!= E
; ++I
) {
448 ExecutionEngine::runStaticConstructorsDestructors(**I
, isDtors
);
452 void 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());
462 Function
*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())
473 GlobalVariable
*MCJIT::FindGlobalVariableNamedInModulePtrSet(StringRef Name
,
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())
486 Function
*MCJIT::FindFunctionNamed(StringRef FnName
) {
487 Function
*F
= FindFunctionNamedInModulePtrSet(
488 FnName
, OwnedModules
.begin_added(), OwnedModules
.end_added());
490 F
= FindFunctionNamedInModulePtrSet(FnName
, OwnedModules
.begin_loaded(),
491 OwnedModules
.end_loaded());
493 F
= FindFunctionNamedInModulePtrSet(FnName
, OwnedModules
.begin_finalized(),
494 OwnedModules
.end_finalized());
498 GlobalVariable
*MCJIT::FindGlobalVariableNamed(StringRef Name
, bool AllowInternal
) {
499 GlobalVariable
*GV
= FindGlobalVariableNamedInModulePtrSet(
500 Name
, AllowInternal
, OwnedModules
.begin_added(), OwnedModules
.end_added());
502 GV
= FindGlobalVariableNamedInModulePtrSet(Name
, AllowInternal
, OwnedModules
.begin_loaded(),
503 OwnedModules
.end_loaded());
505 GV
= FindGlobalVariableNamedInModulePtrSet(Name
, AllowInternal
, OwnedModules
.begin_finalized(),
506 OwnedModules
.end_finalized());
510 GenericValue
MCJIT::runFunction(Function
*F
, ArrayRef
<GenericValue
> ArgValues
) {
511 assert(F
&& "Function *F was null at entry to run()");
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();
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)!");
525 // Handle some common cases first. These cases correspond to common `main'
527 if (RetTy
->isIntegerTy(32) || RetTy
->isVoidTy()) {
528 switch (ArgValues
.size()) {
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
;
536 // Call the function.
538 rv
.IntVal
= APInt(32, PF(ArgValues
[0].IntVal
.getZExtValue(),
539 (char **)GVTOP(ArgValues
[1]),
540 (const char **)GVTOP(ArgValues
[2])));
545 if (FTy
->getParamType(0)->isIntegerTy(32) &&
546 FTy
->getParamType(1)->isPointerTy()) {
547 int (*PF
)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr
;
549 // Call the function.
551 rv
.IntVal
= APInt(32, PF(ArgValues
[0].IntVal
.getZExtValue(),
552 (char **)GVTOP(ArgValues
[1])));
557 if (FTy
->getNumParams() == 1 &&
558 FTy
->getParamType(0)->isIntegerTy(32)) {
560 int (*PF
)(int) = (int(*)(int))(intptr_t)FPtr
;
561 rv
.IntVal
= APInt(32, PF(ArgValues
[0].IntVal
.getZExtValue()));
568 // Handle cases where no arguments are passed first.
569 if (ArgValues
.empty()) {
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();
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
)());
586 llvm_unreachable("Integer types > 64 bits not supported");
590 rv
.IntVal
= APInt(32, ((int (*)())(intptr_t)FPtr
)(), true);
592 case Type::FloatTyID
:
593 rv
.FloatVal
= ((float(*)())(intptr_t)FPtr
)();
595 case Type::DoubleTyID
:
596 rv
.DoubleVal
= ((double(*)())(intptr_t)FPtr
)();
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
)());
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.");
613 void *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
));
623 /// If a LazyFunctionCreator is installed, use it to get/create the function.
624 if (LazyFunctionCreator
)
625 if (void *RP
= LazyFunctionCreator(std::string(Name
)))
628 if (AbortOnFailure
) {
629 report_fatal_error("Program used external function '"+Name
+
630 "' which could not be resolved!");
635 void MCJIT::RegisterJITEventListener(JITEventListener
*L
) {
638 std::lock_guard
<sys::Mutex
> locked(lock
);
639 EventListeners
.push_back(L
);
642 void MCJIT::UnregisterJITEventListener(JITEventListener
*L
) {
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();
653 void MCJIT::notifyObjectLoaded(const object::ObjectFile
&Obj
,
654 const RuntimeDyld::LoadedObjectInfo
&L
) {
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
);
663 void MCJIT::notifyFreeingObject(const object::ObjectFile
&Obj
) {
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
);
672 LinkingSymbolResolver::findSymbol(const std::string
&Name
) {
673 auto Result
= ParentEngine
.findSymbol(Name
, false);
676 if (ParentEngine
.isSymbolSearchingDisabled())
678 return ClientResolver
->findSymbol(Name
);
681 void LinkingSymbolResolver::anchor() {}