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