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/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 | |
30 | using namespace llvm; |
31 | |
32 | namespace { |
33 | |
34 | static struct RegisterJIT { |
35 | RegisterJIT() { MCJIT::Register(); } |
36 | } JITRegistrator; |
37 | |
38 | } |
39 | |
40 | extern "C" void LLVMLinkInMCJIT() { |
41 | } |
42 | |
43 | ExecutionEngine * |
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. |
49 | // |
50 | // FIXME: Don't do this here. |
51 | sys::DynamicLibrary::LoadLibraryPermanently(Filename: nullptr, ErrMsg: 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 | |
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), |
71 | ObjCache(nullptr) { |
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. |
76 | // |
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. |
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(M: std::move(First)); |
89 | RegisterJITEventListener(L: JITEventListener::createGDBRegistrationListener()); |
90 | } |
91 | |
92 | MCJIT::~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: *Obj); |
100 | |
101 | Archives.clear(); |
102 | } |
103 | |
104 | void 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(M: std::move(M)); |
111 | } |
112 | |
113 | bool MCJIT::removeModule(Module *M) { |
114 | std::lock_guard<sys::Mutex> locked(lock); |
115 | return OwnedModules.removeModule(M); |
116 | } |
117 | |
118 | void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) { |
119 | std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(O: *Obj); |
120 | if (Dyld.hasError()) |
121 | report_fatal_error(reason: Dyld.getErrorString()); |
122 | |
123 | notifyObjectLoaded(Obj: *Obj, L: *L); |
124 | |
125 | LoadedObjects.push_back(Elt: std::move(Obj)); |
126 | } |
127 | |
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(args&: ObjFile, args&: MemBuf) = Obj.takeBinary(); |
132 | addObjectFile(Obj: std::move(ObjFile)); |
133 | Buffers.push_back(Elt: std::move(MemBuf)); |
134 | } |
135 | |
136 | void MCJIT::addArchive(object::OwningBinary<object::Archive> A) { |
137 | Archives.push_back(Elt: std::move(A)); |
138 | } |
139 | |
140 | void MCJIT::setObjectCache(ObjectCache* NewCache) { |
141 | std::lock_guard<sys::Mutex> locked(lock); |
142 | ObjCache = NewCache; |
143 | } |
144 | |
145 | std::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 been |
151 | // materialized already. |
152 | cantFail(Err: M->materializeAll()); |
153 | |
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. |
157 | |
158 | legacy::PassManager PM; |
159 | |
160 | // The RuntimeDyld will take ownership of this shortly |
161 | SmallVector<char, 4096> ObjBufferSV; |
162 | raw_svector_ostream ObjStream(ObjBufferSV); |
163 | |
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(reason: "Target does not support MC emission!" ); |
168 | |
169 | // Initialize passes. |
170 | PM.run(M&: *M); |
171 | // Flush the output buffer to get the generated code into memory |
172 | |
173 | auto CompiledObjBuffer = std::make_unique<SmallVectorMemoryBuffer>( |
174 | args: std::move(ObjBufferSV), /*RequiresNullTerminator=*/args: 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 OK |
180 | // to create a temporary object here and delete it after the call. |
181 | MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef(); |
182 | ObjCache->notifyObjectCompiled(M, Obj: MB); |
183 | } |
184 | |
185 | return CompiledObjBuffer; |
186 | } |
187 | |
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); |
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 supported |
197 | if (OwnedModules.hasModuleBeenLoaded(M)) |
198 | return; |
199 | |
200 | std::unique_ptr<MemoryBuffer> ObjectToLoad; |
201 | // Try to load the pre-compiled object from cache if possible |
202 | 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 object |
208 | 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(Object: ObjectToLoad->getMemBufferRef()); |
217 | if (!LoadedObject) { |
218 | std::string Buf; |
219 | raw_string_ostream OS(Buf); |
220 | logAllUnhandledErrors(E: LoadedObject.takeError(), OS); |
221 | report_fatal_error(reason: Twine(Buf)); |
222 | } |
223 | std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = |
224 | Dyld.loadObject(O: *LoadedObject.get()); |
225 | |
226 | if (Dyld.hasError()) |
227 | report_fatal_error(reason: Dyld.getErrorString()); |
228 | |
229 | notifyObjectLoaded(Obj: *LoadedObject.get(), L: *L); |
230 | |
231 | Buffers.push_back(Elt: std::move(ObjectToLoad)); |
232 | LoadedObjects.push_back(Elt: std::move(*LoadedObject)); |
233 | |
234 | OwnedModules.markModuleAsLoaded(M); |
235 | } |
236 | |
237 | void 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 loaded |
250 | Dyld.registerEHFrames(); |
251 | |
252 | // Set page permissions. |
253 | MemMgr->finalizeMemory(); |
254 | } |
255 | |
256 | // FIXME: Rename this. |
257 | void 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 | |
270 | void 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 | |
283 | JITSymbol MCJIT::findExistingSymbol(const std::string &Name) { |
284 | if (void *Addr = getPointerToGlobalIfAvailable(S: 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 | |
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(Start: 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(Name: DemangledName); |
306 | if (F && !F->isDeclaration()) |
307 | return M; |
308 | if (!CheckFunctionsOnly) { |
309 | GlobalVariable *G = M->getGlobalVariable(Name: 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 | |
319 | uint64_t MCJIT::getSymbolAddress(const std::string &Name, |
320 | bool CheckFunctionsOnly) { |
321 | std::string MangledName; |
322 | { |
323 | raw_string_ostream MangledNameStream(MangledName); |
324 | Mangler::getNameWithPrefix(OS&: MangledNameStream, GVName: Name, DL: getDataLayout()); |
325 | } |
326 | if (auto Sym = findSymbol(Name: MangledName, CheckFunctionsOnly)) { |
327 | if (auto AddrOrErr = Sym.getAddress()) |
328 | return *AddrOrErr; |
329 | else |
330 | report_fatal_error(Err: AddrOrErr.takeError()); |
331 | } else if (auto Err = Sym.takeError()) |
332 | report_fatal_error(Err: Sym.takeError()); |
333 | return 0; |
334 | } |
335 | |
336 | JITSymbol 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 Archive |
347 | auto OptionalChildOrErr = A->findSym(name: Name); |
348 | if (!OptionalChildOrErr) |
349 | report_fatal_error(Err: 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(Err: 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(Obj: 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 | |
393 | uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) { |
394 | std::lock_guard<sys::Mutex> locked(lock); |
395 | uint64_t Result = getSymbolAddress(Name, CheckFunctionsOnly: false); |
396 | if (Result != 0) |
397 | finalizeLoadedModules(); |
398 | return Result; |
399 | } |
400 | |
401 | uint64_t MCJIT::getFunctionAddress(const std::string &Name) { |
402 | std::lock_guard<sys::Mutex> locked(lock); |
403 | uint64_t Result = getSymbolAddress(Name, CheckFunctionsOnly: true); |
404 | if (Result != 0) |
405 | finalizeLoadedModules(); |
406 | return Result; |
407 | } |
408 | |
409 | // Deprecated. Use getFunctionAddress instead. |
410 | void *MCJIT::getPointerToFunction(Function *F) { |
411 | std::lock_guard<sys::Mutex> locked(lock); |
412 | |
413 | Mangler Mang; |
414 | SmallString<128> Name; |
415 | TM->getNameWithPrefix(Name, GV: F, Mang); |
416 | |
417 | if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { |
418 | bool AbortOnFailure = !F->hasExternalWeakLinkage(); |
419 | void *Addr = getPointerToNamedFunction(Name, AbortOnFailure); |
420 | updateGlobalMapping(GV: 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 probably |
434 | // 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 the |
441 | // load address of the symbol, not the local address. |
442 | return (void*)Dyld.getSymbol(Name).getAddress(); |
443 | } |
444 | |
445 | void MCJIT::runStaticConstructorsDestructorsInModulePtrSet( |
446 | bool isDtors, ModulePtrSet::iterator I, ModulePtrSet::iterator E) { |
447 | for (; I != E; ++I) { |
448 | ExecutionEngine::runStaticConstructorsDestructors(module&: **I, isDtors); |
449 | } |
450 | } |
451 | |
452 | void MCJIT::runStaticConstructorsDestructors(bool isDtors) { |
453 | // Execute global ctors/dtors for each module in the program. |
454 | runStaticConstructorsDestructorsInModulePtrSet( |
455 | isDtors, I: OwnedModules.begin_added(), E: OwnedModules.end_added()); |
456 | runStaticConstructorsDestructorsInModulePtrSet( |
457 | isDtors, I: OwnedModules.begin_loaded(), E: OwnedModules.end_loaded()); |
458 | runStaticConstructorsDestructorsInModulePtrSet( |
459 | isDtors, I: OwnedModules.begin_finalized(), E: OwnedModules.end_finalized()); |
460 | } |
461 | |
462 | Function *MCJIT::FindFunctionNamedInModulePtrSet(StringRef FnName, |
463 | ModulePtrSet::iterator I, |
464 | ModulePtrSet::iterator E) { |
465 | for (; I != E; ++I) { |
466 | Function *F = (*I)->getFunction(Name: FnName); |
467 | if (F && !F->isDeclaration()) |
468 | return F; |
469 | } |
470 | return nullptr; |
471 | } |
472 | |
473 | GlobalVariable *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 | |
486 | Function *MCJIT::FindFunctionNamed(StringRef FnName) { |
487 | Function *F = FindFunctionNamedInModulePtrSet( |
488 | FnName, I: OwnedModules.begin_added(), E: OwnedModules.end_added()); |
489 | if (!F) |
490 | F = FindFunctionNamedInModulePtrSet(FnName, I: OwnedModules.begin_loaded(), |
491 | E: OwnedModules.end_loaded()); |
492 | if (!F) |
493 | F = FindFunctionNamedInModulePtrSet(FnName, I: OwnedModules.begin_finalized(), |
494 | E: OwnedModules.end_finalized()); |
495 | return F; |
496 | } |
497 | |
498 | GlobalVariable *MCJIT::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) { |
499 | GlobalVariable *GV = FindGlobalVariableNamedInModulePtrSet( |
500 | Name, AllowInternal, I: OwnedModules.begin_added(), E: OwnedModules.end_added()); |
501 | if (!GV) |
502 | GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, I: OwnedModules.begin_loaded(), |
503 | E: OwnedModules.end_loaded()); |
504 | if (!GV) |
505 | GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, I: OwnedModules.begin_finalized(), |
506 | E: OwnedModules.end_finalized()); |
507 | return GV; |
508 | } |
509 | |
510 | GenericValue 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(M: 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(Bitwidth: 32) || RetTy->isVoidTy()) { |
528 | switch (ArgValues.size()) { |
529 | case 3: |
530 | if (FTy->getParamType(i: 0)->isIntegerTy(Bitwidth: 32) && |
531 | FTy->getParamType(i: 1)->isPointerTy() && |
532 | FTy->getParamType(i: 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(GV: ArgValues[1]), |
540 | (const char **)GVTOP(GV: ArgValues[2]))); |
541 | return rv; |
542 | } |
543 | break; |
544 | case 2: |
545 | if (FTy->getParamType(i: 0)->isIntegerTy(Bitwidth: 32) && |
546 | FTy->getParamType(i: 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(GV: ArgValues[1]))); |
553 | return rv; |
554 | } |
555 | break; |
556 | case 1: |
557 | if (FTy->getNumParams() == 1 && |
558 | FTy->getParamType(i: 0)->isIntegerTy(Bitwidth: 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>(Val: 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 | else |
586 | 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(P: ((void*(*)())(intptr_t)FPtr)()); |
604 | } |
605 | } |
606 | |
607 | report_fatal_error(reason: "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 | |
613 | void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) { |
614 | if (!isSymbolSearchingDisabled()) { |
615 | if (auto Sym = Resolver.findSymbol(Name: 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(Err: 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(reason: "Program used external function '" +Name+ |
630 | "' which could not be resolved!" ); |
631 | } |
632 | return nullptr; |
633 | } |
634 | |
635 | void MCJIT::RegisterJITEventListener(JITEventListener *L) { |
636 | if (!L) |
637 | return; |
638 | std::lock_guard<sys::Mutex> locked(lock); |
639 | EventListeners.push_back(x: L); |
640 | } |
641 | |
642 | void MCJIT::UnregisterJITEventListener(JITEventListener *L) { |
643 | if (!L) |
644 | return; |
645 | std::lock_guard<sys::Mutex> locked(lock); |
646 | auto I = find(Range: reverse(C&: EventListeners), Val: L); |
647 | if (I != EventListeners.rend()) { |
648 | std::swap(a&: *I, b&: EventListeners.back()); |
649 | EventListeners.pop_back(); |
650 | } |
651 | } |
652 | |
653 | void 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(EE: this, Obj); |
659 | for (JITEventListener *EL : EventListeners) |
660 | EL->notifyObjectLoaded(K: Key, Obj, L); |
661 | } |
662 | |
663 | void 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(K: Key); |
669 | } |
670 | |
671 | JITSymbol |
672 | LinkingSymbolResolver::findSymbol(const std::string &Name) { |
673 | auto Result = ParentEngine.findSymbol(Name, CheckFunctionsOnly: false); |
674 | if (Result) |
675 | return Result; |
676 | if (ParentEngine.isSymbolSearchingDisabled()) |
677 | return nullptr; |
678 | return ClientResolver->findSymbol(Name); |
679 | } |
680 | |
681 | void LinkingSymbolResolver::anchor() {} |
682 | |