15a440378SAlex Zinenko //===- ExecutionEngine.cpp - MLIR Execution engine and utils --------------===// 25a440378SAlex Zinenko // 330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information. 556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65a440378SAlex Zinenko // 756222a06SMehdi Amini //===----------------------------------------------------------------------===// 85a440378SAlex Zinenko // 95a440378SAlex Zinenko // This file implements the execution engine for MLIR modules based on LLVM Orc 105a440378SAlex Zinenko // JIT engine. 115a440378SAlex Zinenko // 125a440378SAlex Zinenko //===----------------------------------------------------------------------===// 135a440378SAlex Zinenko #include "mlir/ExecutionEngine/ExecutionEngine.h" 1469040d5bSStephan Herhut #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 15*65fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h" 1606e81010SJacques Pienaar #include "mlir/Support/FileUtilities.h" 175a440378SAlex Zinenko #include "mlir/Target/LLVMIR.h" 185a440378SAlex Zinenko 19c3f0ed7bSRiver Riddle #include "llvm/ExecutionEngine/JITEventListener.h" 20fe3594f7SNicolas Vasilache #include "llvm/ExecutionEngine/ObjectCache.h" 215a440378SAlex Zinenko #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 225a440378SAlex Zinenko #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 235a440378SAlex Zinenko #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 248093f17aSAlex Zinenko #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" 255a440378SAlex Zinenko #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 265a440378SAlex Zinenko #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 275a440378SAlex Zinenko #include "llvm/ExecutionEngine/SectionMemoryManager.h" 285a440378SAlex Zinenko #include "llvm/IR/IRBuilder.h" 299f2ce5b9SHaruki Imai #include "llvm/MC/SubtargetFeature.h" 3053bb528bSMehdi Amini #include "llvm/Support/Debug.h" 315a440378SAlex Zinenko #include "llvm/Support/Error.h" 3290dbec26SMehdi Amini #include "llvm/Support/Host.h" 335a440378SAlex Zinenko #include "llvm/Support/TargetRegistry.h" 3406e81010SJacques Pienaar #include "llvm/Support/ToolOutputFile.h" 355a440378SAlex Zinenko 3653bb528bSMehdi Amini #define DEBUG_TYPE "execution-engine" 3753bb528bSMehdi Amini 385a440378SAlex Zinenko using namespace mlir; 39fe3594f7SNicolas Vasilache using llvm::dbgs; 405a440378SAlex Zinenko using llvm::Error; 41fe3594f7SNicolas Vasilache using llvm::errs; 425a440378SAlex Zinenko using llvm::Expected; 43fe3594f7SNicolas Vasilache using llvm::LLVMContext; 44fe3594f7SNicolas Vasilache using llvm::MemoryBuffer; 45fe3594f7SNicolas Vasilache using llvm::MemoryBufferRef; 46fe3594f7SNicolas Vasilache using llvm::Module; 47fe3594f7SNicolas Vasilache using llvm::SectionMemoryManager; 48fe3594f7SNicolas Vasilache using llvm::StringError; 49fe3594f7SNicolas Vasilache using llvm::Triple; 50fe3594f7SNicolas Vasilache using llvm::orc::DynamicLibrarySearchGenerator; 51fe3594f7SNicolas Vasilache using llvm::orc::ExecutionSession; 52fe3594f7SNicolas Vasilache using llvm::orc::IRCompileLayer; 53fe3594f7SNicolas Vasilache using llvm::orc::JITTargetMachineBuilder; 543a11ca7bSEugene Zhulenev using llvm::orc::MangleAndInterner; 55fe3594f7SNicolas Vasilache using llvm::orc::RTDyldObjectLinkingLayer; 563a11ca7bSEugene Zhulenev using llvm::orc::SymbolMap; 57fe3594f7SNicolas Vasilache using llvm::orc::ThreadSafeModule; 58fe3594f7SNicolas Vasilache using llvm::orc::TMOwningSimpleCompiler; 596aa5cc8bSNicolas Vasilache 602666b973SRiver Riddle /// Wrap a string into an llvm::StringError. 612666b973SRiver Riddle static Error make_string_error(const Twine &message) { 62fe3594f7SNicolas Vasilache return llvm::make_error<StringError>(message.str(), 635a440378SAlex Zinenko llvm::inconvertibleErrorCode()); 645a440378SAlex Zinenko } 655a440378SAlex Zinenko 66fe3594f7SNicolas Vasilache void SimpleObjectCache::notifyObjectCompiled(const Module *M, 67fe3594f7SNicolas Vasilache MemoryBufferRef ObjBuffer) { 6806e81010SJacques Pienaar cachedObjects[M->getModuleIdentifier()] = MemoryBuffer::getMemBufferCopy( 69fe3594f7SNicolas Vasilache ObjBuffer.getBuffer(), ObjBuffer.getBufferIdentifier()); 70fe3594f7SNicolas Vasilache } 71fe3594f7SNicolas Vasilache 72fe3594f7SNicolas Vasilache std::unique_ptr<MemoryBuffer> SimpleObjectCache::getObject(const Module *M) { 7306e81010SJacques Pienaar auto I = cachedObjects.find(M->getModuleIdentifier()); 7406e81010SJacques Pienaar if (I == cachedObjects.end()) { 7553bb528bSMehdi Amini LLVM_DEBUG(dbgs() << "No object for " << M->getModuleIdentifier() 7653bb528bSMehdi Amini << " in cache. Compiling.\n"); 77fe3594f7SNicolas Vasilache return nullptr; 78fe3594f7SNicolas Vasilache } 7953bb528bSMehdi Amini LLVM_DEBUG(dbgs() << "Object for " << M->getModuleIdentifier() 8053bb528bSMehdi Amini << " loaded from cache.\n"); 81fe3594f7SNicolas Vasilache return MemoryBuffer::getMemBuffer(I->second->getMemBufferRef()); 82fe3594f7SNicolas Vasilache } 83fe3594f7SNicolas Vasilache 844562e389SRiver Riddle void SimpleObjectCache::dumpToObjectFile(StringRef outputFilename) { 8506e81010SJacques Pienaar // Set up the output file. 8606e81010SJacques Pienaar std::string errorMessage; 8706e81010SJacques Pienaar auto file = openOutputFile(outputFilename, &errorMessage); 8806e81010SJacques Pienaar if (!file) { 8906e81010SJacques Pienaar llvm::errs() << errorMessage << "\n"; 9006e81010SJacques Pienaar return; 9106e81010SJacques Pienaar } 9206e81010SJacques Pienaar 9306e81010SJacques Pienaar // Dump the object generated for a single module to the output file. 9406e81010SJacques Pienaar assert(cachedObjects.size() == 1 && "Expected only one object entry."); 9506e81010SJacques Pienaar auto &cachedObject = cachedObjects.begin()->second; 9606e81010SJacques Pienaar file->os() << cachedObject->getBuffer(); 9706e81010SJacques Pienaar file->keep(); 9806e81010SJacques Pienaar } 9906e81010SJacques Pienaar 1004562e389SRiver Riddle void ExecutionEngine::dumpToObjectFile(StringRef filename) { 10106e81010SJacques Pienaar cache->dumpToObjectFile(filename); 10206e81010SJacques Pienaar } 10306e81010SJacques Pienaar 1043a11ca7bSEugene Zhulenev void ExecutionEngine::registerSymbols( 1053a11ca7bSEugene Zhulenev llvm::function_ref<SymbolMap(MangleAndInterner)> symbolMap) { 1063a11ca7bSEugene Zhulenev auto &mainJitDylib = jit->getMainJITDylib(); 1073a11ca7bSEugene Zhulenev cantFail(mainJitDylib.define( 1083a11ca7bSEugene Zhulenev absoluteSymbols(symbolMap(llvm::orc::MangleAndInterner( 1093a11ca7bSEugene Zhulenev mainJitDylib.getExecutionSession(), jit->getDataLayout()))))); 1103a11ca7bSEugene Zhulenev } 1113a11ca7bSEugene Zhulenev 1125a440378SAlex Zinenko // Setup LLVM target triple from the current machine. 113fe3594f7SNicolas Vasilache bool ExecutionEngine::setupTargetTriple(Module *llvmModule) { 1145a440378SAlex Zinenko // Setup the machine properties from the current architecture. 1155a440378SAlex Zinenko auto targetTriple = llvm::sys::getDefaultTargetTriple(); 1165a440378SAlex Zinenko std::string errorMessage; 1175a440378SAlex Zinenko auto target = llvm::TargetRegistry::lookupTarget(targetTriple, errorMessage); 1185a440378SAlex Zinenko if (!target) { 119fe3594f7SNicolas Vasilache errs() << "NO target: " << errorMessage << "\n"; 1205a440378SAlex Zinenko return true; 1215a440378SAlex Zinenko } 1229f2ce5b9SHaruki Imai 1239f2ce5b9SHaruki Imai std::string cpu(llvm::sys::getHostCPUName()); 1249f2ce5b9SHaruki Imai llvm::SubtargetFeatures features; 1259f2ce5b9SHaruki Imai llvm::StringMap<bool> hostFeatures; 1269f2ce5b9SHaruki Imai 1279f2ce5b9SHaruki Imai if (llvm::sys::getHostCPUFeatures(hostFeatures)) 1289f2ce5b9SHaruki Imai for (auto &f : hostFeatures) 1299f2ce5b9SHaruki Imai features.AddFeature(f.first(), f.second); 1309f2ce5b9SHaruki Imai 1319f2ce5b9SHaruki Imai std::unique_ptr<llvm::TargetMachine> machine(target->createTargetMachine( 1329f2ce5b9SHaruki Imai targetTriple, cpu, features.getString(), {}, {})); 1335a440378SAlex Zinenko llvmModule->setDataLayout(machine->createDataLayout()); 1345a440378SAlex Zinenko llvmModule->setTargetTriple(targetTriple); 1355a440378SAlex Zinenko return false; 1365a440378SAlex Zinenko } 1375a440378SAlex Zinenko 1385a440378SAlex Zinenko static std::string makePackedFunctionName(StringRef name) { 1395a440378SAlex Zinenko return "_mlir_" + name.str(); 1405a440378SAlex Zinenko } 1415a440378SAlex Zinenko 1425a440378SAlex Zinenko // For each function in the LLVM module, define an interface function that wraps 1435a440378SAlex Zinenko // all the arguments of the original function and all its results into an i8** 1445a440378SAlex Zinenko // pointer to provide a unified invocation interface. 145df186507SBenjamin Kramer static void packFunctionArguments(Module *module) { 1465a440378SAlex Zinenko auto &ctx = module->getContext(); 1475a440378SAlex Zinenko llvm::IRBuilder<> builder(ctx); 1484562e389SRiver Riddle DenseSet<llvm::Function *> interfaceFunctions; 1495a440378SAlex Zinenko for (auto &func : module->getFunctionList()) { 1505a440378SAlex Zinenko if (func.isDeclaration()) { 1515a440378SAlex Zinenko continue; 1525a440378SAlex Zinenko } 1535a440378SAlex Zinenko if (interfaceFunctions.count(&func)) { 1545a440378SAlex Zinenko continue; 1555a440378SAlex Zinenko } 1565a440378SAlex Zinenko 1575a440378SAlex Zinenko // Given a function `foo(<...>)`, define the interface function 1585a440378SAlex Zinenko // `mlir_foo(i8**)`. 1595a440378SAlex Zinenko auto newType = llvm::FunctionType::get( 1605a440378SAlex Zinenko builder.getVoidTy(), builder.getInt8PtrTy()->getPointerTo(), 1615a440378SAlex Zinenko /*isVarArg=*/false); 1625a440378SAlex Zinenko auto newName = makePackedFunctionName(func.getName()); 163c46b0feaSRiver Riddle auto funcCst = module->getOrInsertFunction(newName, newType); 1644562e389SRiver Riddle llvm::Function *interfaceFunc = cast<llvm::Function>(funcCst.getCallee()); 1655a440378SAlex Zinenko interfaceFunctions.insert(interfaceFunc); 1665a440378SAlex Zinenko 1675a440378SAlex Zinenko // Extract the arguments from the type-erased argument list and cast them to 1685a440378SAlex Zinenko // the proper types. 1695a440378SAlex Zinenko auto bb = llvm::BasicBlock::Create(ctx); 1705a440378SAlex Zinenko bb->insertInto(interfaceFunc); 1715a440378SAlex Zinenko builder.SetInsertPoint(bb); 1725a440378SAlex Zinenko llvm::Value *argList = interfaceFunc->arg_begin(); 1734562e389SRiver Riddle SmallVector<llvm::Value *, 8> args; 1745a440378SAlex Zinenko args.reserve(llvm::size(func.args())); 1755a440378SAlex Zinenko for (auto &indexedArg : llvm::enumerate(func.args())) { 1765a440378SAlex Zinenko llvm::Value *argIndex = llvm::Constant::getIntegerValue( 1774562e389SRiver Riddle builder.getInt64Ty(), APInt(64, indexedArg.index())); 1785a440378SAlex Zinenko llvm::Value *argPtrPtr = builder.CreateGEP(argList, argIndex); 1795a440378SAlex Zinenko llvm::Value *argPtr = builder.CreateLoad(argPtrPtr); 1805a440378SAlex Zinenko argPtr = builder.CreateBitCast( 1815a440378SAlex Zinenko argPtr, indexedArg.value().getType()->getPointerTo()); 1825a440378SAlex Zinenko llvm::Value *arg = builder.CreateLoad(argPtr); 1835a440378SAlex Zinenko args.push_back(arg); 1845a440378SAlex Zinenko } 1855a440378SAlex Zinenko 1865a440378SAlex Zinenko // Call the implementation function with the extracted arguments. 1875a440378SAlex Zinenko llvm::Value *result = builder.CreateCall(&func, args); 1885a440378SAlex Zinenko 1895a440378SAlex Zinenko // Assuming the result is one value, potentially of type `void`. 1905a440378SAlex Zinenko if (!result->getType()->isVoidTy()) { 1915a440378SAlex Zinenko llvm::Value *retIndex = llvm::Constant::getIntegerValue( 1924562e389SRiver Riddle builder.getInt64Ty(), APInt(64, llvm::size(func.args()))); 1935a440378SAlex Zinenko llvm::Value *retPtrPtr = builder.CreateGEP(argList, retIndex); 1945a440378SAlex Zinenko llvm::Value *retPtr = builder.CreateLoad(retPtrPtr); 1955a440378SAlex Zinenko retPtr = builder.CreateBitCast(retPtr, result->getType()->getPointerTo()); 1965a440378SAlex Zinenko builder.CreateStore(result, retPtr); 1975a440378SAlex Zinenko } 1985a440378SAlex Zinenko 1995a440378SAlex Zinenko // The interface function returns void. 2005a440378SAlex Zinenko builder.CreateRetVoid(); 2015a440378SAlex Zinenko } 2025a440378SAlex Zinenko } 2035a440378SAlex Zinenko 204d1186fcbSaartbik ExecutionEngine::ExecutionEngine(bool enableObjectCache, 2053c5dd586SEugene Zhulenev bool enableGDBNotificationListener, 2063c5dd586SEugene Zhulenev bool enablePerfNotificationListener) 207d1186fcbSaartbik : cache(enableObjectCache ? new SimpleObjectCache() : nullptr), 208d1186fcbSaartbik gdbListener(enableGDBNotificationListener 209d1186fcbSaartbik ? llvm::JITEventListener::createGDBRegistrationListener() 2103c5dd586SEugene Zhulenev : nullptr), 2113c5dd586SEugene Zhulenev perfListener(enablePerfNotificationListener 2123c5dd586SEugene Zhulenev ? llvm::JITEventListener::createPerfJITEventListener() 213d1186fcbSaartbik : nullptr) {} 21406e81010SJacques Pienaar 21506e81010SJacques Pienaar Expected<std::unique_ptr<ExecutionEngine>> ExecutionEngine::create( 21689808ce7SGeorge Mitenkov ModuleOp m, 21789808ce7SGeorge Mitenkov llvm::function_ref<std::unique_ptr<llvm::Module>(ModuleOp, 21889808ce7SGeorge Mitenkov llvm::LLVMContext &)> 21989808ce7SGeorge Mitenkov llvmModuleBuilder, 22089808ce7SGeorge Mitenkov llvm::function_ref<Error(llvm::Module *)> transformer, 221713ab0ddSUday Bondhugula Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel, 222d1186fcbSaartbik ArrayRef<StringRef> sharedLibPaths, bool enableObjectCache, 2233c5dd586SEugene Zhulenev bool enableGDBNotificationListener, bool enablePerfNotificationListener) { 224d1186fcbSaartbik auto engine = std::make_unique<ExecutionEngine>( 2253c5dd586SEugene Zhulenev enableObjectCache, enableGDBNotificationListener, 2263c5dd586SEugene Zhulenev enablePerfNotificationListener); 2275a440378SAlex Zinenko 228fe3594f7SNicolas Vasilache std::unique_ptr<llvm::LLVMContext> ctx(new llvm::LLVMContext); 22989808ce7SGeorge Mitenkov auto llvmModule = llvmModuleBuilder ? llvmModuleBuilder(m, *ctx) 23089808ce7SGeorge Mitenkov : translateModuleToLLVMIR(m, *ctx); 2315a440378SAlex Zinenko if (!llvmModule) 2325a440378SAlex Zinenko return make_string_error("could not convert to LLVM IR"); 2335a440378SAlex Zinenko // FIXME: the triple should be passed to the translation or dialect conversion 2345a440378SAlex Zinenko // instead of this. Currently, the LLVM module created above has no triple 2355a440378SAlex Zinenko // associated with it. 2365a440378SAlex Zinenko setupTargetTriple(llvmModule.get()); 2375a440378SAlex Zinenko packFunctionArguments(llvmModule.get()); 2385a440378SAlex Zinenko 239db1c197bSAlex Zinenko auto dataLayout = llvmModule->getDataLayout(); 240fe3594f7SNicolas Vasilache 241fe3594f7SNicolas Vasilache // Callback to create the object layer with symbol resolution to current 242fe3594f7SNicolas Vasilache // process and dynamically linked libraries. 243fe3594f7SNicolas Vasilache auto objectLinkingLayerCreator = [&](ExecutionSession &session, 244fe3594f7SNicolas Vasilache const Triple &TT) { 245fe3594f7SNicolas Vasilache auto objectLayer = std::make_unique<RTDyldObjectLinkingLayer>( 246fe3594f7SNicolas Vasilache session, []() { return std::make_unique<SectionMemoryManager>(); }); 2473c5dd586SEugene Zhulenev 2483c5dd586SEugene Zhulenev // Register JIT event listeners if they are enabled. 2493c5dd586SEugene Zhulenev if (engine->gdbListener) 2503c5dd586SEugene Zhulenev objectLayer->registerJITEventListener(*engine->gdbListener); 2513c5dd586SEugene Zhulenev if (engine->perfListener) 2523c5dd586SEugene Zhulenev objectLayer->registerJITEventListener(*engine->perfListener); 253fe3594f7SNicolas Vasilache 254fe3594f7SNicolas Vasilache // Resolve symbols from shared libraries. 255fe3594f7SNicolas Vasilache for (auto libPath : sharedLibPaths) { 256fe3594f7SNicolas Vasilache auto mb = llvm::MemoryBuffer::getFile(libPath); 257fe3594f7SNicolas Vasilache if (!mb) { 258670063ebSAden Grue errs() << "Failed to create MemoryBuffer for: " << libPath 259670063ebSAden Grue << "\nError: " << mb.getError().message() << "\n"; 260fe3594f7SNicolas Vasilache continue; 261fe3594f7SNicolas Vasilache } 262a7504226SRiver Riddle auto &JD = session.createBareJITDylib(std::string(libPath)); 263fe3594f7SNicolas Vasilache auto loaded = DynamicLibrarySearchGenerator::Load( 264fe3594f7SNicolas Vasilache libPath.data(), dataLayout.getGlobalPrefix()); 265fe3594f7SNicolas Vasilache if (!loaded) { 266e38fe4a7SChristian Sigg errs() << "Could not load " << libPath << ":\n " << loaded.takeError() 267e38fe4a7SChristian Sigg << "\n"; 268fe3594f7SNicolas Vasilache continue; 269fe3594f7SNicolas Vasilache } 270fe3594f7SNicolas Vasilache JD.addGenerator(std::move(*loaded)); 271fe3594f7SNicolas Vasilache cantFail(objectLayer->add(JD, std::move(mb.get()))); 272fe3594f7SNicolas Vasilache } 273fe3594f7SNicolas Vasilache 274fe3594f7SNicolas Vasilache return objectLayer; 275fe3594f7SNicolas Vasilache }; 276fe3594f7SNicolas Vasilache 277fe3594f7SNicolas Vasilache // Callback to inspect the cache and recompile on demand. This follows Lang's 278fe3594f7SNicolas Vasilache // LLJITWithObjectCache example. 279fe3594f7SNicolas Vasilache auto compileFunctionCreator = [&](JITTargetMachineBuilder JTMB) 2807984b474SAlex Zinenko -> Expected<std::unique_ptr<IRCompileLayer::IRCompiler>> { 281713ab0ddSUday Bondhugula if (jitCodeGenOptLevel) 282713ab0ddSUday Bondhugula JTMB.setCodeGenOptLevel(jitCodeGenOptLevel.getValue()); 283fe3594f7SNicolas Vasilache auto TM = JTMB.createTargetMachine(); 284fe3594f7SNicolas Vasilache if (!TM) 285fe3594f7SNicolas Vasilache return TM.takeError(); 2867984b474SAlex Zinenko return std::make_unique<TMOwningSimpleCompiler>(std::move(*TM), 2877984b474SAlex Zinenko engine->cache.get()); 288fe3594f7SNicolas Vasilache }; 289fe3594f7SNicolas Vasilache 290fe3594f7SNicolas Vasilache // Create the LLJIT by calling the LLJITBuilder with 2 callbacks. 291fe3594f7SNicolas Vasilache auto jit = 292fe3594f7SNicolas Vasilache cantFail(llvm::orc::LLJITBuilder() 293fe3594f7SNicolas Vasilache .setCompileFunctionCreator(compileFunctionCreator) 294fe3594f7SNicolas Vasilache .setObjectLinkingLayerCreator(objectLinkingLayerCreator) 295fe3594f7SNicolas Vasilache .create()); 296fe3594f7SNicolas Vasilache 297fe3594f7SNicolas Vasilache // Add a ThreadSafemodule to the engine and return. 298db1c197bSAlex Zinenko ThreadSafeModule tsm(std::move(llvmModule), std::move(ctx)); 299cf26e5faSNicolas Vasilache if (transformer) 300cf26e5faSNicolas Vasilache cantFail(tsm.withModuleDo( 301cf26e5faSNicolas Vasilache [&](llvm::Module &module) { return transformer(&module); })); 302fe3594f7SNicolas Vasilache cantFail(jit->addIRModule(std::move(tsm))); 303fe3594f7SNicolas Vasilache engine->jit = std::move(jit); 3045a440378SAlex Zinenko 3056d60d869SRiver Riddle // Resolve symbols that are statically linked in the current process. 3066d60d869SRiver Riddle llvm::orc::JITDylib &mainJD = engine->jit->getMainJITDylib(); 3076d60d869SRiver Riddle mainJD.addGenerator( 3086d60d869SRiver Riddle cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( 3096d60d869SRiver Riddle dataLayout.getGlobalPrefix()))); 3106d60d869SRiver Riddle 311e7111fd6SJacques Pienaar return std::move(engine); 3125a440378SAlex Zinenko } 3135a440378SAlex Zinenko 3145a440378SAlex Zinenko Expected<void (*)(void **)> ExecutionEngine::lookup(StringRef name) const { 3155a440378SAlex Zinenko auto expectedSymbol = jit->lookup(makePackedFunctionName(name)); 316d7fbfbb1SAlex Zinenko 317d7fbfbb1SAlex Zinenko // JIT lookup may return an Error referring to strings stored internally by 318d7fbfbb1SAlex Zinenko // the JIT. If the Error outlives the ExecutionEngine, it would want have a 319d7fbfbb1SAlex Zinenko // dangling reference, which is currently caught by an assertion inside JIT 320d7fbfbb1SAlex Zinenko // thanks to hand-rolled reference counting. Rewrap the error message into a 321d7fbfbb1SAlex Zinenko // string before returning. Alternatively, ORC JIT should consider copying 322d7fbfbb1SAlex Zinenko // the string into the error message. 323d7fbfbb1SAlex Zinenko if (!expectedSymbol) { 324d7fbfbb1SAlex Zinenko std::string errorMessage; 325d7fbfbb1SAlex Zinenko llvm::raw_string_ostream os(errorMessage); 326d7fbfbb1SAlex Zinenko llvm::handleAllErrors(expectedSymbol.takeError(), 327d7fbfbb1SAlex Zinenko [&os](llvm::ErrorInfoBase &ei) { ei.log(os); }); 328d7fbfbb1SAlex Zinenko return make_string_error(os.str()); 329d7fbfbb1SAlex Zinenko } 330d7fbfbb1SAlex Zinenko 3315a440378SAlex Zinenko auto rawFPtr = expectedSymbol->getAddress(); 3325a440378SAlex Zinenko auto fptr = reinterpret_cast<void (*)(void **)>(rawFPtr); 3335a440378SAlex Zinenko if (!fptr) 3345a440378SAlex Zinenko return make_string_error("looked up function is null"); 3355a440378SAlex Zinenko return fptr; 3365a440378SAlex Zinenko } 337629f5b7fSNicolas Vasilache 338fe3594f7SNicolas Vasilache Error ExecutionEngine::invoke(StringRef name, MutableArrayRef<void *> args) { 339629f5b7fSNicolas Vasilache auto expectedFPtr = lookup(name); 340629f5b7fSNicolas Vasilache if (!expectedFPtr) 341629f5b7fSNicolas Vasilache return expectedFPtr.takeError(); 342629f5b7fSNicolas Vasilache auto fptr = *expectedFPtr; 343629f5b7fSNicolas Vasilache 344629f5b7fSNicolas Vasilache (*fptr)(args.data()); 345629f5b7fSNicolas Vasilache 346fe3594f7SNicolas Vasilache return Error::success(); 347629f5b7fSNicolas Vasilache } 348