diff options
author | Lang Hames <lhames@gmail.com> | 2017-07-07 02:59:13 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2017-07-07 02:59:13 +0000 |
commit | 4ce98662e7d109b4579c35945345db685ae5b3fb (patch) | |
tree | 4538ca3c0131f3275286aac4347bf712ed0068e7 | |
parent | b909f11a319ae62e683d1f9d82e28a05b360b8ae (diff) | |
download | bcm5719-llvm-4ce98662e7d109b4579c35945345db685ae5b3fb.tar.gz bcm5719-llvm-4ce98662e7d109b4579c35945345db685ae5b3fb.zip |
[ORC] Errorize the ORC APIs.
This patch updates the ORC layers and utilities to return and propagate
llvm::Errors where appropriate. This is necessary to allow ORC to safely handle
error cases in cross-process and remote JITing.
llvm-svn: 307350
42 files changed, 570 insertions, 281 deletions
diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h index 5ce8c9f152a..5a2148a14a1 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h @@ -75,8 +75,8 @@ public: // Add the set to the JIT with the resolver we created above and a newly // created SectionMemoryManager. - return CompileLayer.addModule(std::move(M), - std::move(Resolver)); + return cantFail(CompileLayer.addModule(std::move(M), + std::move(Resolver))); } JITSymbol findSymbol(const std::string Name) { @@ -87,7 +87,7 @@ public: } void removeModule(ModuleHandle H) { - CompileLayer.removeModule(H); + cantFail(CompileLayer.removeModule(H)); } }; diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp index 163caa6872d..2471344c6d6 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp @@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h index e524c0e69b4..9a295f1566c 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h @@ -88,8 +88,8 @@ public: // Add the set to the JIT with the resolver we created above and a newly // created SectionMemoryManager. - return OptimizeLayer.addModule(std::move(M), - std::move(Resolver)); + return cantFail(OptimizeLayer.addModule(std::move(M), + std::move(Resolver))); } JITSymbol findSymbol(const std::string Name) { @@ -100,7 +100,7 @@ public: } void removeModule(ModuleHandle H) { - OptimizeLayer.removeModule(H); + cantFail(OptimizeLayer.removeModule(H)); } private: diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp index 163caa6872d..2471344c6d6 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp @@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h index d1a4b0b7248..a03f5ce5e23 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h @@ -101,8 +101,7 @@ public: // Add the set to the JIT with the resolver we created above and a newly // created SectionMemoryManager. - return CODLayer.addModule(std::move(M), - std::move(Resolver)); + return cantFail(CODLayer.addModule(std::move(M), std::move(Resolver))); } JITSymbol findSymbol(const std::string Name) { @@ -113,7 +112,7 @@ public: } void removeModule(ModuleHandle H) { - CODLayer.removeModule(H); + cantFail(CODLayer.removeModule(H)); } private: diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp index 163caa6872d..2471344c6d6 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp @@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h index c0d1b69ed59..d10e4748f1a 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h @@ -128,8 +128,8 @@ public: // Add the set to the JIT with the resolver we created above and a newly // created SectionMemoryManager. - return OptimizeLayer.addModule(std::move(M), - std::move(Resolver)); + return cantFail(OptimizeLayer.addModule(std::move(M), + std::move(Resolver))); } Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) { @@ -175,7 +175,7 @@ public: addModule(std::move(M)); auto Sym = findSymbol(SharedFnAST->getName() + "$impl"); assert(Sym && "Couldn't find compiled function?"); - JITTargetAddress SymAddr = Sym.getAddress(); + JITTargetAddress SymAddr = cantFail(Sym.getAddress()); if (auto Err = IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()), SymAddr)) { @@ -195,7 +195,7 @@ public: } void removeModule(ModuleHandle H) { - OptimizeLayer.removeModule(H); + cantFail(OptimizeLayer.removeModule(H)); } private: diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp index ff4b5220105..ed8ae31ba0f 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp @@ -1153,7 +1153,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h index 94057c2b101..7ea535b3af5 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h @@ -157,8 +157,8 @@ public: // Add the set to the JIT with the resolver we created above and a newly // created SectionMemoryManager. - return OptimizeLayer.addModule(std::move(M), - std::move(Resolver)); + return cantFail(OptimizeLayer.addModule(std::move(M), + std::move(Resolver))); } Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) { @@ -204,7 +204,7 @@ public: addModule(std::move(M)); auto Sym = findSymbol(SharedFnAST->getName() + "$impl"); assert(Sym && "Couldn't find compiled function?"); - JITTargetAddress SymAddr = Sym.getAddress(); + JITTargetAddress SymAddr = cantFail(Sym.getAddress()); if (auto Err = IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()), SymAddr)) { @@ -228,7 +228,7 @@ public: } void removeModule(ModuleHandle H) { - OptimizeLayer.removeModule(H); + cantFail(OptimizeLayer.removeModule(H)); } private: diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp index edd050959d6..7bbc06a0958 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp @@ -1177,7 +1177,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - ExitOnErr(TheJIT->executeRemoteExpr(ExprSymbol.getAddress())); + ExitOnErr(TheJIT->executeRemoteExpr(cantFail(ExprSymbol.getAddress()))); // Delete the anonymous expression module from the JIT. TheJIT->removeModule(H); diff --git a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp index cf7d6c2bee0..921fa890804 100644 --- a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp @@ -611,7 +611,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp index 6852973bae4..2d23bdb26c2 100644 --- a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp @@ -885,7 +885,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp index 0c222173558..b5e4495539f 100644 --- a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp @@ -1004,7 +1004,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp index 79ac7b33d7a..32f4a658c5d 100644 --- a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp @@ -1173,7 +1173,7 @@ static void HandleTopLevelExpression() { // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); + double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. diff --git a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h index e389781d8f4..90ae3d1041e 100644 --- a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h @@ -63,8 +63,8 @@ public: return JITSymbol(nullptr); }, [](const std::string &S) { return nullptr; }); - auto H = CompileLayer.addModule(std::move(M), - std::move(Resolver)); + auto H = cantFail(CompileLayer.addModule(std::move(M), + std::move(Resolver))); ModuleHandles.push_back(H); return H; @@ -72,7 +72,7 @@ public: void removeModule(ModuleHandleT H) { ModuleHandles.erase(find(ModuleHandles, H)); - CompileLayer.removeModule(H); + cantFail(CompileLayer.removeModule(H)); } JITSymbol findSymbol(const std::string Name) { diff --git a/llvm/include/llvm-c/OrcBindings.h b/llvm/include/llvm-c/OrcBindings.h index d86ea880888..7ee39543135 100644 --- a/llvm/include/llvm-c/OrcBindings.h +++ b/llvm/include/llvm-c/OrcBindings.h @@ -113,8 +113,9 @@ void LLVMOrcDisposeMangledSymbol(char *MangledSymbol); /** * Create a lazy compile callback. */ -LLVMOrcTargetAddress +LLVMOrcErrorCode LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx); @@ -135,8 +136,9 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, /** * Add module to be eagerly compiled. */ -LLVMOrcModuleHandle +LLVMOrcErrorCode LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, LLVMSharedModuleRef Mod, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx); @@ -144,8 +146,9 @@ LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, /** * Add module to be lazily compiled one function at a time. */ -LLVMOrcModuleHandle +LLVMOrcErrorCode LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, LLVMSharedModuleRef Mod, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx); @@ -153,10 +156,11 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, /** * Add an object file. */ -LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, - LLVMSharedObjectBufferRef Obj, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); +LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMSharedObjectBufferRef Obj, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); /** * Remove a module set from the JIT. @@ -164,18 +168,20 @@ LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, * This works for all modules that can be added via OrcAdd*, including object * files. */ -void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H); +LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle H); /** * Get symbol address from JIT instance. */ -LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, - const char *SymbolName); +LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + const char *SymbolName); /** * Dispose of an ORC JIT stack. */ -void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); +LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); #ifdef __cplusplus } diff --git a/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/llvm/include/llvm/ExecutionEngine/JITSymbol.h index f09e95fddb9..eef562be820 100644 --- a/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -21,6 +21,8 @@ #include <functional> #include <string> +#include "llvm/Support/Error.h" + namespace llvm { class GlobalValue; @@ -41,10 +43,11 @@ public: enum FlagNames : UnderlyingType { None = 0, - Weak = 1U << 0, - Common = 1U << 1, - Absolute = 1U << 2, - Exported = 1U << 3 + HasError = 1U << 0, + Weak = 1U << 1, + Common = 1U << 2, + Absolute = 1U << 3, + Exported = 1U << 4 }; /// @brief Default-construct a JITSymbolFlags instance. @@ -53,6 +56,11 @@ public: /// @brief Construct a JITSymbolFlags instance from the given flags. JITSymbolFlags(FlagNames Flags) : Flags(Flags) {} + /// @brief Return true if there was an error retrieving this symbol. + bool hasError() const { + return (Flags & HasError) == HasError; + } + /// @brief Returns true is the Weak flag is set. bool isWeak() const { return (Flags & Weak) == Weak; @@ -113,11 +121,17 @@ private: /// @brief Represents a symbol in the JIT. class JITSymbol { public: - using GetAddressFtor = std::function<JITTargetAddress()>; + using GetAddressFtor = std::function<Expected<JITTargetAddress>()>; + + /// @brief Create a 'null' symbol, used to represent a "symbol not found" + /// result from a successful (non-erroneous) lookup. + JITSymbol(std::nullptr_t) + : CachedAddr(0) {} - /// @brief Create a 'null' symbol that represents failure to find a symbol - /// definition. - JITSymbol(std::nullptr_t) {} + /// @brief Create a JITSymbol representing an error in the symbol lookup + /// process (e.g. a network failure during a remote lookup). + JITSymbol(Error Err) + : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {} /// @brief Create a symbol for a definition with a known address. JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags) @@ -139,16 +153,57 @@ public: JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags) : GetAddress(std::move(GetAddress)), Flags(Flags) {} + JITSymbol(const JITSymbol&) = delete; + JITSymbol& operator=(const JITSymbol&) = delete; + + JITSymbol(JITSymbol &&Other) + : GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) { + if (Flags.hasError()) + Err = std::move(Other.Err); + else + CachedAddr = std::move(Other.CachedAddr); + } + + JITSymbol& operator=(JITSymbol &&Other) { + GetAddress = std::move(Other.GetAddress); + Flags = std::move(Other.Flags); + if (Flags.hasError()) + Err = std::move(Other.Err); + else + CachedAddr = std::move(Other.CachedAddr); + return *this; + } + + ~JITSymbol() { + if (Flags.hasError()) + Err.~Error(); + else + CachedAddr.~JITTargetAddress(); + } + /// @brief Returns true if the symbol exists, false otherwise. - explicit operator bool() const { return CachedAddr || GetAddress; } + explicit operator bool() const { + return !Flags.hasError() && (CachedAddr || GetAddress); + } + + /// @brief Move the error field value out of this JITSymbol. + Error takeError() { + if (Flags.hasError()) + return std::move(Err); + return Error::success(); + } /// @brief Get the address of the symbol in the target address space. Returns /// '0' if the symbol does not exist. - JITTargetAddress getAddress() { + Expected<JITTargetAddress> getAddress() { + assert(!Flags.hasError() && "getAddress called on error value"); if (GetAddress) { - CachedAddr = GetAddress(); - assert(CachedAddr && "Symbol could not be materialized."); - GetAddress = nullptr; + if (auto CachedAddrOrErr = GetAddress()) { + GetAddress = nullptr; + CachedAddr = *CachedAddrOrErr; + assert(CachedAddr && "Symbol could not be materialized."); + } else + return CachedAddrOrErr.takeError(); } return CachedAddr; } @@ -157,7 +212,10 @@ public: private: GetAddressFtor GetAddress; - JITTargetAddress CachedAddr = 0; + union { + JITTargetAddress CachedAddr; + Error Err; + }; JITSymbolFlags Flags; }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 3984a00bef5..c1acca38682 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -176,12 +176,16 @@ private: for (auto BLH : BaseLayerHandles) if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly)) return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); return nullptr; } - void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { + Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { for (auto &BLH : BaseLayerHandles) - BaseLayer.removeModule(BLH); + if (auto Err = BaseLayer.removeModule(BLH)) + return Err; + return Error::success(); } std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver; @@ -216,13 +220,15 @@ public: CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} ~CompileOnDemandLayer() { + // FIXME: Report error on log. while (!LogicalDylibs.empty()) - removeModule(LogicalDylibs.begin()); + consumeError(removeModule(LogicalDylibs.begin())); } /// @brief Add a module to the compile-on-demand layer. - ModuleHandleT addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { + Expected<ModuleHandleT> + addModule(std::shared_ptr<Module> M, + std::shared_ptr<JITSymbolResolver> Resolver) { LogicalDylibs.push_back(LogicalDylib()); auto &LD = LogicalDylibs.back(); @@ -230,23 +236,25 @@ public: LD.StubsMgr = CreateIndirectStubsManager(); // Process each of the modules in this module set. - addLogicalModule(LD, std::move(M)); + if (auto Err = addLogicalModule(LD, std::move(M))) + return std::move(Err); return std::prev(LogicalDylibs.end()); } /// @brief Add extra modules to an existing logical module. - void addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) { - addLogicalModule(*H, std::move(M)); + Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) { + return addLogicalModule(*H, std::move(M)); } /// @brief Remove the module represented by the given handle. /// /// This will remove all modules in the layers below that were derived from /// the module represented by H. - void removeModule(ModuleHandleT H) { - H->removeModulesFromBaseLayer(BaseLayer); + Error removeModule(ModuleHandleT H) { + auto Err = H->removeModulesFromBaseLayer(BaseLayer); LogicalDylibs.erase(H); + return Err; } /// @brief Search for the given named symbol. @@ -260,6 +268,8 @@ public: return Sym; if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly)) return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); } return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } @@ -298,7 +308,7 @@ public: private: - void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) { + Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) { // Rename all static functions / globals to $static.X : // This will unique the names across all modules in the logical dylib, @@ -324,9 +334,12 @@ private: // Skip weak functions for which we already have definitions. auto MangledName = mangle(F.getName(), DL); - if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) + if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) { if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false)) continue; + else if (auto Err = Sym.takeError()) + return std::move(Err); + } // Record all functions defined by this module. if (CloneStubsIntoPartitions) @@ -339,9 +352,15 @@ private: StubInits[MangledName] = std::make_pair(CCInfo.getAddress(), JITSymbolFlags::fromGlobalValue(F)); - CCInfo.setCompileAction([this, &LD, LMId, &F]() { - return this->extractAndCompile(LD, LMId, F); - }); + CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress { + if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) + return *FnImplAddrOrErr; + else { + // FIXME: Report error, return to 'abort' or something similar. + consumeError(FnImplAddrOrErr.takeError()); + return 0; + } + }); } auto EC = LD.StubsMgr->createStubs(StubInits); @@ -356,7 +375,7 @@ private: // empty globals module. if (SrcM.global_empty() && SrcM.alias_empty() && !SrcM.getModuleFlagsMetadata()) - return; + return Error::success(); // Create the GlobalValues module. auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(), @@ -382,8 +401,9 @@ private: // Initializers may refer to functions declared (but not defined) in this // module. Build a materializer to clone decls on demand. + Error MaterializerErrors = Error::success(); auto Materializer = createLambdaMaterializer( - [&LD, &GVsM](Value *V) -> Value* { + [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* { if (auto *F = dyn_cast<Function>(V)) { // Decls in the original module just get cloned. if (F->isDeclaration()) @@ -394,13 +414,24 @@ private: // instead. const DataLayout &DL = GVsM->getDataLayout(); std::string FName = mangle(F->getName(), DL); - auto StubSym = LD.StubsMgr->findStub(FName, false); unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType()); - ConstantInt *StubAddr = - ConstantInt::get(GVsM->getContext(), - APInt(PtrBitWidth, StubSym.getAddress())); + JITTargetAddress StubAddr = 0; + + // Get the address for the stub. If we encounter an error while + // doing so, stash it in the MaterializerErrors variable and use a + // null address as a placeholder. + if (auto StubSym = LD.StubsMgr->findStub(FName, false)) { + if (auto StubAddrOrErr = StubSym.getAddress()) + StubAddr = *StubAddrOrErr; + else + MaterializerErrors = joinErrors(std::move(MaterializerErrors), + StubAddrOrErr.takeError()); + } + + ConstantInt *StubAddrCI = + ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr)); Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr, - StubAddr, F->getType()); + StubAddrCI, F->getType()); return GlobalAlias::create(F->getFunctionType(), F->getType()->getAddressSpace(), F->getLinkage(), F->getName(), @@ -424,21 +455,31 @@ private: NewA->setAliasee(cast<Constant>(Init)); } + if (MaterializerErrors) + return MaterializerErrors; + // Build a resolver for the globals module and add it to the base layer. auto GVsResolver = createLambdaResolver( - [this, &LD](const std::string &Name) { + [this, &LD](const std::string &Name) -> JITSymbol { if (auto Sym = LD.StubsMgr->findStub(Name, false)) return Sym; if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); }, [&LD](const std::string &Name) { return LD.ExternalSymbolResolver->findSymbol(Name); }); - auto GVsH = BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver)); - LD.BaseLayerHandles.push_back(GVsH); + if (auto GVsHOrErr = + BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver))) + LD.BaseLayerHandles.push_back(*GVsHOrErr); + else + return GVsHOrErr.takeError(); + + return Error::success(); } static std::string mangle(StringRef Name, const DataLayout &DL) { @@ -450,7 +491,7 @@ private: return MangledName; } - JITTargetAddress + Expected<JITTargetAddress> extractAndCompile(LogicalDylib &LD, typename LogicalDylib::SourceModuleHandle LMId, Function &F) { @@ -463,34 +504,42 @@ private: // Grab the name of the function being called here. std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout()); - auto Part = Partition(F); - auto PartH = emitPartition(LD, LMId, Part); - JITTargetAddress CalledAddr = 0; - for (auto *SubF : Part) { - std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); - auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false); - assert(FnBodySym && "Couldn't find function body."); - - JITTargetAddress FnBodyAddr = FnBodySym.getAddress(); - - // If this is the function we're calling record the address so we can - // return it from this function. - if (SubF == &F) - CalledAddr = FnBodyAddr; - - // Update the function body pointer for the stub. - if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr)) - return 0; - } + auto Part = Partition(F); + if (auto PartHOrErr = emitPartition(LD, LMId, Part)) { + auto &PartH = *PartHOrErr; + for (auto *SubF : Part) { + std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); + if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) { + if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) { + JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr; + + // If this is the function we're calling record the address so we can + // return it from this function. + if (SubF == &F) + CalledAddr = FnBodyAddr; + + // Update the function body pointer for the stub. + if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr)) + return 0; + + } else + return FnBodyAddrOrErr.takeError(); + } else if (auto Err = FnBodySym.takeError()) + return std::move(Err); + else + llvm_unreachable("Function not emitted for partition"); + } - LD.BaseLayerHandles.push_back(PartH); + LD.BaseLayerHandles.push_back(PartH); + } else + return PartHOrErr.takeError(); return CalledAddr; } template <typename PartitionT> - BaseLayerModuleHandleT + Expected<BaseLayerModuleHandleT> emitPartition(LogicalDylib &LD, typename LogicalDylib::SourceModuleHandle LMId, const PartitionT &Part) { @@ -554,9 +603,11 @@ private: // Create memory manager and symbol resolver. auto Resolver = createLambdaResolver( - [this, &LD](const std::string &Name) { + [this, &LD](const std::string &Name) -> JITSymbol { if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); }, [&LD](const std::string &Name) { diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index bf8cca40684..d9b45c6a1e2 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -17,6 +17,8 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/iterator_range.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/Orc/OrcError.h" #include <algorithm> #include <cstdint> #include <string> @@ -99,19 +101,24 @@ public: /// @brief Run the recorded constructors/destructors through the given JIT /// layer. - bool runViaLayer(JITLayerT &JITLayer) const { + Error runViaLayer(JITLayerT &JITLayer) const { using CtorDtorTy = void (*)(); - bool Error = false; for (const auto &CtorDtorName : CtorDtorNames) if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { - CtorDtorTy CtorDtor = - reinterpret_cast<CtorDtorTy>( - static_cast<uintptr_t>(CtorDtorSym.getAddress())); - CtorDtor(); - } else - Error = true; - return !Error; + if (auto AddrOrErr = CtorDtorSym.getAddress()) { + CtorDtorTy CtorDtor = + reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr)); + CtorDtor(); + } else + return AddrOrErr.takeError(); + } else { + if (auto Err = CtorDtorSym.takeError()) + return Err; + else + return make_error<JITSymbolNotFound>(CtorDtorName); + } + return Error::success(); } private: diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index 340af262c07..fadd334bed0 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -50,15 +50,18 @@ public: /// along with the given memory manager and symbol resolver. /// /// @return A handle for the added module. - ModuleHandleT addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { + Expected<ModuleHandleT> + addModule(std::shared_ptr<Module> M, + std::shared_ptr<JITSymbolResolver> Resolver) { using CompileResult = decltype(Compile(*M)); auto Obj = std::make_shared<CompileResult>(Compile(*M)); return BaseLayer.addObject(std::move(Obj), std::move(Resolver)); } /// @brief Remove the module associated with the handle H. - void removeModule(ModuleHandleT H) { BaseLayer.removeObject(H); } + Error removeModule(ModuleHandleT H) { + return BaseLayer.removeObject(H); + } /// @brief Search for the given named symbol. /// @param Name The name of the symbol to search for. @@ -84,8 +87,8 @@ public: /// @brief Immediately emit and finalize the module represented by the given /// handle. /// @param H Handle for module to emit/finalize. - void emitAndFinalize(ModuleHandleT H) { - BaseLayer.emitAndFinalize(H); + Error emitAndFinalize(ModuleHandleT H) { + return BaseLayer.emitAndFinalize(H); } private: diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 90d8a3281b4..476061afda5 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -42,13 +42,14 @@ public: /// the layer below, along with the memory manager and symbol resolver. /// /// @return A handle for the added modules. - ModuleHandleT addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { + Expected<ModuleHandleT> + addModule(std::shared_ptr<Module> M, + std::shared_ptr<JITSymbolResolver> Resolver) { return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver)); } /// @brief Remove the module associated with the handle H. - void removeModule(ModuleHandleT H) { BaseLayer.removeModule(H); } + Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); } /// @brief Search for the given named symbol. /// @param Name The name of the symbol to search for. @@ -74,8 +75,8 @@ public: /// @brief Immediately emit and finalize the module represented by the given /// handle. /// @param H Handle for module to emit/finalize. - void emitAndFinalize(ModuleHandleT H) { - BaseLayer.emitAndFinalize(H); + Error emitAndFinalize(ModuleHandleT H) { + return BaseLayer.emitAndFinalize(H); } /// @brief Access the transform functor directly. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index fe770c5ce59..1dba2146313 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -60,16 +60,24 @@ private: std::string PName = Name; JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV); auto GetAddress = - [this, ExportedSymbolsOnly, PName, &B]() -> JITTargetAddress { + [this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> { if (this->EmitState == Emitting) return 0; else if (this->EmitState == NotEmitted) { this->EmitState = Emitting; - Handle = this->emitToBaseLayer(B); + if (auto HandleOrErr = this->emitToBaseLayer(B)) + Handle = std::move(*HandleOrErr); + else + return HandleOrErr.takeError(); this->EmitState = Emitted; } - auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly); - return Sym.getAddress(); + if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly)) + return Sym.getAddress(); + else if (auto Err = Sym.takeError()) + return std::move(Err); + else + llvm_unreachable("Successful symbol lookup should return " + "definition address here"); }; return JITSymbol(std::move(GetAddress), Flags); } else @@ -127,7 +135,7 @@ private: return buildMangledSymbols(Name, ExportedSymbolsOnly); } - BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) { + Expected<BaseLayerHandleT> emitToBaseLayer(BaseLayerT &BaseLayer) { // We don't need the mangled names set any more: Once we've emitted this // to the base layer we'll just look for symbols there. MangledSymbols.reset(); @@ -204,8 +212,9 @@ public: LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} /// @brief Add the given module to the lazy emitting layer. - ModuleHandleT addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { + Expected<ModuleHandleT> + addModule(std::shared_ptr<Module> M, + std::shared_ptr<JITSymbolResolver> Resolver) { return ModuleList.insert( ModuleList.end(), llvm::make_unique<EmissionDeferredModule>(std::move(M), @@ -216,7 +225,7 @@ public: /// /// This method will free the memory associated with the given module, both /// in this layer, and the base layer. - void removeModule(ModuleHandleT H) { + Error removeModule(ModuleHandleT H) { (*H)->removeModuleFromBaseLayer(BaseLayer); ModuleList.erase(H); } @@ -251,8 +260,8 @@ public: /// @brief Immediately emit and finalize the module represented by the given /// handle. /// @param H Handle for module to emit/finalize. - void emitAndFinalize(ModuleHandleT H) { - (*H)->emitAndFinalize(BaseLayer); + Error emitAndFinalize(ModuleHandleT H) { + return (*H)->emitAndFinalize(BaseLayer); } }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index b98a78aa708..cb47e7520b1 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -44,13 +44,13 @@ public: /// /// @return A handle for the added objects. template <typename ObjectPtr> - ObjHandleT addObject(ObjectPtr Obj, - std::shared_ptr<JITSymbolResolver> Resolver) { + Expected<ObjHandleT> addObject(ObjectPtr Obj, + std::shared_ptr<JITSymbolResolver> Resolver) { return BaseLayer.addObject(Transform(std::move(Obj)), std::move(Resolver)); } /// @brief Remove the object set associated with the handle H. - void removeObject(ObjHandleT H) { BaseLayer.removeObject(H); } + Error removeObject(ObjHandleT H) { return BaseLayer.removeObject(H); } /// @brief Search for the given named symbol. /// @param Name The name of the symbol to search for. @@ -76,7 +76,9 @@ public: /// @brief Immediately emit and finalize the object set represented by the /// given handle. /// @param H Handle for object set to emit/finalize. - void emitAndFinalize(ObjHandleT H) { BaseLayer.emitAndFinalize(H); } + Error emitAndFinalize(ObjHandleT H) { + return BaseLayer.emitAndFinalize(H); + } /// @brief Map section addresses for the objects associated with the handle H. void mapSectionAddress(ObjHandleT H, const void *LocalAddress, diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h index cbb40fad022..e6374b70967 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h @@ -22,7 +22,8 @@ namespace orc { enum class OrcErrorCode : int { // RPC Errors - RemoteAllocatorDoesNotExist = 1, + JITSymbolNotFound = 1, + RemoteAllocatorDoesNotExist, RemoteAllocatorIdAlreadyInUse, RemoteMProtectAddrUnrecognized, RemoteIndirectStubsOwnerDoesNotExist, @@ -37,6 +38,18 @@ enum class OrcErrorCode : int { std::error_code orcError(OrcErrorCode ErrCode); +class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> { +public: + static char ID; + + JITSymbolNotFound(std::string SymbolName); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + const std::string &getSymbolName() const; +private: + std::string SymbolName; +}; + } // End namespace orc. } // End namespace llvm. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index ca6fb44b113..e1016ef95f0 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -258,8 +258,8 @@ public: /// /// @return A handle that can be used to refer to the loaded objects (for /// symbol searching, finalization, freeing memory, etc.). - ObjHandleT addObject(ObjectPtr Obj, - std::shared_ptr<JITSymbolResolver> Resolver) { + Expected<ObjHandleT> addObject(ObjectPtr Obj, + std::shared_ptr<JITSymbolResolver> Resolver) { auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld, const ObjectPtr &ObjToLoad, std::function<void()> LOSHandleLoad) { @@ -299,9 +299,10 @@ public: /// indirectly) will result in undefined behavior. If dependence tracking is /// required to detect or resolve such issues it should be added at a higher /// layer. - void removeObject(ObjHandleT H) { + Error removeObject(ObjHandleT H) { // How do we invalidate the symbols in H? LinkedObjList.erase(H); + return Error::success(); } /// @brief Search for the given named symbol. @@ -338,8 +339,9 @@ public: /// @brief Immediately emit and finalize the object set represented by the /// given handle. /// @param H Handle for object set to emit/finalize. - void emitAndFinalize(ObjHandleT H) { + Error emitAndFinalize(ObjHandleT H) { (*H)->finalize(); + return Error::success(); } private: diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index ff8749fbfed..1164d60ffc1 100644 --- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -317,7 +317,13 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name, raw_string_ostream MangledNameStream(MangledName); Mangler::getNameWithPrefix(MangledNameStream, Name, getDataLayout()); } - return findSymbol(MangledName, CheckFunctionsOnly).getAddress(); + if (auto Sym = findSymbol(MangledName, CheckFunctionsOnly)) { + if (auto AddrOrErr = Sym.getAddress()) + return *AddrOrErr; + else + report_fatal_error(AddrOrErr.takeError()); + } else + report_fatal_error(Sym.takeError()); } JITSymbol MCJIT::findSymbol(const std::string &Name, @@ -599,11 +605,12 @@ GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) { void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) { if (!isSymbolSearchingDisabled()) { - void *ptr = - reinterpret_cast<void*>( - static_cast<uintptr_t>(Resolver.findSymbol(Name).getAddress())); - if (ptr) - return ptr; + if (auto Sym = Resolver.findSymbol(Name)) { + if (auto AddrOrErr = Sym.getAddress()) + return reinterpret_cast<void*>( + static_cast<uintptr_t>(*AddrOrErr)); + } else if (auto Err = Sym.takeError()) + report_fatal_error(std::move(Err)); } /// If a LazyFunctionCreator is installed, use it to get/create the function. diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp index 5fe259f80b6..de80cb1d0dd 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp @@ -60,12 +60,13 @@ void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName, void LLVMOrcDisposeMangledSymbol(char *MangledName) { delete[] MangledName; } -LLVMOrcTargetAddress +LLVMOrcErrorCode LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) { OrcCBindingsStack &J = *unwrap(JITStack); - return J.createLazyCompileCallback(Callback, CallbackCtx); + return J.createLazyCompileCallback(*RetAddr, Callback, CallbackCtx); } LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, @@ -82,38 +83,44 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, return J.setIndirectStubPointer(StubName, NewAddr); } -LLVMOrcModuleHandle +LLVMOrcErrorCode LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, LLVMSharedModuleRef Mod, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx) { OrcCBindingsStack &J = *unwrap(JITStack); std::shared_ptr<Module> *M(unwrap(Mod)); - return J.addIRModuleEager(*M, SymbolResolver, SymbolResolverCtx); + return J.addIRModuleEager(*RetHandle, *M, SymbolResolver, SymbolResolverCtx); } -LLVMOrcModuleHandle +LLVMOrcErrorCode LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, LLVMSharedModuleRef Mod, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx) { OrcCBindingsStack &J = *unwrap(JITStack); std::shared_ptr<Module> *M(unwrap(Mod)); - return J.addIRModuleLazy(*M, SymbolResolver, SymbolResolverCtx); + return J.addIRModuleLazy(*RetHandle, *M, SymbolResolver, SymbolResolverCtx); } -void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H) { +LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle H) { OrcCBindingsStack &J = *unwrap(JITStack); - J.removeModule(H); + return J.removeModule(H); } -LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, - const char *SymbolName) { +LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + const char *SymbolName) { OrcCBindingsStack &J = *unwrap(JITStack); - auto Sym = J.findSymbol(SymbolName, true); - return Sym.getAddress(); + return J.findSymbolAddress(*RetAddr, SymbolName, true); } -void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) { - delete unwrap(JITStack); +LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) { + auto *J = unwrap(JITStack); + auto Err = J->shutdown(); + delete J; + return Err; } diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index e6c950e15fb..e38decf94f3 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -70,7 +70,7 @@ private: virtual JITSymbol findSymbolIn(const std::string &Name, bool ExportedSymbolsOnly) = 0; - virtual void removeModule() = 0; + virtual Error removeModule() = 0; }; template <typename LayerT> class GenericHandleImpl : public GenericHandle { @@ -83,7 +83,7 @@ private: return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly); } - void removeModule() override { return Layer.removeModule(Handle); } + Error removeModule() override { return Layer.removeModule(Handle); } private: LayerT &Layer; @@ -116,12 +116,14 @@ public: CXXRuntimeOverrides( [this](const std::string &S) { return mangle(S); }) {} - ~OrcCBindingsStack() { + LLVMOrcErrorCode shutdown() { // Run any destructors registered with __cxa_atexit. CXXRuntimeOverrides.runDestructors(); // Run any IR destructors. for (auto &DtorRunner : IRStaticDestructorRunners) - DtorRunner.runViaLayer(*this); + if (auto Err = DtorRunner.runViaLayer(*this)) + return mapError(std::move(Err)); + return LLVMOrcErrSuccess; } std::string mangle(StringRef Name) { @@ -138,14 +140,17 @@ public: return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr)); } - JITTargetAddress - createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback, + + LLVMOrcErrorCode + createLazyCompileCallback(JITTargetAddress &RetAddr, + LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) { auto CCInfo = CCMgr->getCompileCallback(); CCInfo.setCompileAction([=]() -> JITTargetAddress { return Callback(wrap(this), CallbackCtx); }); - return CCInfo.getAddress(); + RetAddr = CCInfo.getAddress(); + return LLVMOrcErrSuccess; } LLVMOrcErrorCode createIndirectStub(StringRef StubName, @@ -164,7 +169,7 @@ public: void *ExternalResolverCtx) { return orc::createLambdaResolver( [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) - -> JITSymbol { + -> JITSymbol { // Search order: // 1. JIT'd symbols. // 2. Runtime overrides. @@ -172,6 +177,9 @@ public: if (auto Sym = CODLayer.findSymbol(Name, true)) return Sym; + else if (auto Err = Sym.takeError()) + return Sym.takeError(); + if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) return Sym; @@ -182,16 +190,19 @@ public: return JITSymbol(nullptr); }, - [](const std::string &Name) { + [](const std::string &Name) -> JITSymbol { return JITSymbol(nullptr); }); } template <typename LayerT> - ModuleHandleT addIRModule(LayerT &Layer, std::shared_ptr<Module> M, - std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr, - LLVMOrcSymbolResolverFn ExternalResolver, - void *ExternalResolverCtx) { + LLVMOrcErrorCode + addIRModule(ModuleHandleT &RetHandle, LayerT &Layer, + std::shared_ptr<Module> M, + std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr, + LLVMOrcSymbolResolverFn ExternalResolver, + void *ExternalResolverCtx) { + // Attach a data-layout if one isn't already present. if (M->getDataLayout().isDefault()) M->setDataLayout(DL); @@ -208,42 +219,52 @@ public: auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx); // Add the module to the JIT. - auto LH = Layer.addModule(std::move(M), std::move(Resolver)); - ModuleHandleT H = createHandle(Layer, LH); + ModuleHandleT H; + if (auto LHOrErr = Layer.addModule(std::move(M), std::move(Resolver))) + H = createHandle(Layer, *LHOrErr); + else + return mapError(LHOrErr.takeError()); // Run the static constructors, and save the static destructor runner for // execution when the JIT is torn down. orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames), H); - CtorRunner.runViaLayer(*this); + if (auto Err = CtorRunner.runViaLayer(*this)) + return mapError(std::move(Err)); IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H); - return H; + RetHandle = H; + return LLVMOrcErrSuccess; } - ModuleHandleT addIRModuleEager(std::shared_ptr<Module> M, - LLVMOrcSymbolResolverFn ExternalResolver, - void *ExternalResolverCtx) { - return addIRModule(CompileLayer, std::move(M), + LLVMOrcErrorCode addIRModuleEager(ModuleHandleT &RetHandle, + std::shared_ptr<Module> M, + LLVMOrcSymbolResolverFn ExternalResolver, + void *ExternalResolverCtx) { + return addIRModule(RetHandle, CompileLayer, std::move(M), llvm::make_unique<SectionMemoryManager>(), std::move(ExternalResolver), ExternalResolverCtx); } - ModuleHandleT addIRModuleLazy(std::shared_ptr<Module> M, - LLVMOrcSymbolResolverFn ExternalResolver, - void *ExternalResolverCtx) { - return addIRModule(CODLayer, std::move(M), + LLVMOrcErrorCode addIRModuleLazy(ModuleHandleT &RetHandle, + std::shared_ptr<Module> M, + LLVMOrcSymbolResolverFn ExternalResolver, + void *ExternalResolverCtx) { + return addIRModule(RetHandle, CODLayer, std::move(M), llvm::make_unique<SectionMemoryManager>(), std::move(ExternalResolver), ExternalResolverCtx); } - void removeModule(ModuleHandleT H) { - GenericHandles[H]->removeModule(); + LLVMOrcErrorCode removeModule(ModuleHandleT H) { + if (auto Err = GenericHandles[H]->removeModule()) + return mapError(std::move(Err)); GenericHandles[H] = nullptr; FreeHandleIndexes.push_back(H); + return LLVMOrcErrSuccess; } - JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + JITSymbol findSymbol(const std::string &Name, + bool ExportedSymbolsOnly) { if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly)) return Sym; return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly); @@ -254,6 +275,26 @@ public: return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly); } + LLVMOrcErrorCode findSymbolAddress(JITTargetAddress &RetAddr, + const std::string &Name, + bool ExportedSymbolsOnly) { + RetAddr = 0; + if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) { + // Successful lookup, non-null symbol: + if (auto AddrOrErr = Sym.getAddress()) { + RetAddr = *AddrOrErr; + return LLVMOrcErrSuccess; + } else + return mapError(AddrOrErr.takeError()); + } else if (auto Err = Sym.takeError()) { + // Lookup failure - report error. + return mapError(std::move(Err)); + } + // Otherwise we had a successful lookup but got a null result. We already + // set RetAddr to '0' above, so just return success. + return LLVMOrcErrSuccess; + } + const std::string &getErrorMessage() const { return ErrMsg; } private: diff --git a/llvm/lib/ExecutionEngine/Orc/OrcError.cpp b/llvm/lib/ExecutionEngine/Orc/OrcError.cpp index 9e70c4ac1db..df2d320e0f7 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcError.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcError.cpp @@ -45,6 +45,8 @@ public: return "Could not negotiate RPC function"; case OrcErrorCode::RPCResponseAbandoned: return "RPC response abandoned"; + case OrcErrorCode::JITSymbolNotFound: + return "JIT symbol not found"; case OrcErrorCode::UnexpectedRPCCall: return "Unexpected RPC call"; case OrcErrorCode::UnexpectedRPCResponse: @@ -63,10 +65,29 @@ static ManagedStatic<OrcErrorCategory> OrcErrCat; namespace llvm { namespace orc { +char JITSymbolNotFound::ID = 0; + std::error_code orcError(OrcErrorCode ErrCode) { typedef std::underlying_type<OrcErrorCode>::type UT; return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat); } +JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName) + : SymbolName(std::move(SymbolName)) {} + +std::error_code JITSymbolNotFound::convertToErrorCode() const { + typedef std::underlying_type<OrcErrorCode>::type UT; + return std::error_code(static_cast<UT>(OrcErrorCode::JITSymbolNotFound), + *OrcErrCat); +} + +void JITSymbolNotFound::log(raw_ostream &OS) const { + OS << "Could not find symbol '" << SymbolName << "'"; +} + +const std::string &JITSymbolNotFound::getSymbolName() const { + return SymbolName; +} + } } diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 8a24de1f24c..346a40405ff 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -202,20 +202,20 @@ public: delete Mod; }; LocalModules.push_back(std::shared_ptr<Module>(MPtr, std::move(Deleter))); - LazyEmitLayer.addModule(LocalModules.back(), Resolver); + cantFail(LazyEmitLayer.addModule(LocalModules.back(), Resolver)); } void addObjectFile(std::unique_ptr<object::ObjectFile> O) override { auto Obj = std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O), nullptr); - ObjectLayer.addObject(std::move(Obj), Resolver); + cantFail(ObjectLayer.addObject(std::move(Obj), Resolver)); } void addObjectFile(object::OwningBinary<object::ObjectFile> O) override { auto Obj = std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O)); - ObjectLayer.addObject(std::move(Obj), Resolver); + cantFail(ObjectLayer.addObject(std::move(Obj), Resolver)); } void addArchive(object::OwningBinary<object::Archive> A) override { @@ -234,7 +234,7 @@ public: } uint64_t getSymbolAddress(StringRef Name) { - return findSymbol(Name).getAddress(); + return cantFail(findSymbol(Name).getAddress()); } JITSymbol findSymbol(StringRef Name) { @@ -323,7 +323,7 @@ private: auto Obj = std::make_shared<object::OwningBinary<object::ObjectFile>>( std::move(ChildObj), nullptr); - ObjectLayer.addObject(std::move(Obj), Resolver); + cantFail(ObjectLayer.addObject(std::move(Obj), Resolver)); if (auto Sym = ObjectLayer.findSymbol(Name, true)) return Sym; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 2b69f1a0269..8198836f7a0 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -128,7 +128,10 @@ void RuntimeDyldImpl::resolveRelocations() { ); // First, resolve relocations associated with external symbols. - resolveExternalSymbols(); + if (auto Err = resolveExternalSymbols()) { + HasError = true; + ErrorStr = toString(std::move(Err)); + } // Iterate over all outstanding relocations for (auto it = Relocations.begin(), e = Relocations.end(); it != e; ++it) { @@ -243,9 +246,11 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { continue; // Then check the symbol resolver to see if there's a definition // elsewhere in this logical dylib. - if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) + if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) { if (Sym.getFlags().isStrongDefinition()) continue; + } else if (auto Err = Sym.takeError()) + return std::move(Err); // else JITSymFlags &= ~JITSymbolFlags::Weak; } @@ -953,7 +958,7 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, } } -void RuntimeDyldImpl::resolveExternalSymbols() { +Error RuntimeDyldImpl::resolveExternalSymbols() { while (!ExternalSymbolRelocations.empty()) { StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin(); @@ -971,10 +976,24 @@ void RuntimeDyldImpl::resolveExternalSymbols() { // This is an external symbol, try to get its address from the symbol // resolver. // First search for the symbol in this logical dylib. - Addr = Resolver.findSymbolInLogicalDylib(Name.data()).getAddress(); + if (auto Sym = Resolver.findSymbolInLogicalDylib(Name.data())) { + if (auto AddrOrErr = Sym.getAddress()) + Addr = *AddrOrErr; + else + return AddrOrErr.takeError(); + } else if (auto Err = Sym.takeError()) + return Err; + // If that fails, try searching for an external symbol. - if (!Addr) - Addr = Resolver.findSymbol(Name.data()).getAddress(); + if (!Addr) { + if (auto Sym = Resolver.findSymbol(Name.data())) { + if (auto AddrOrErr = Sym.getAddress()) + Addr = *AddrOrErr; + else + return AddrOrErr.takeError(); + } else if (auto Err = Sym.takeError()) + return Err; + } // The call to getSymbolAddress may have caused additional modules to // be loaded, which may have added new entries to the // ExternalSymbolRelocations map. Consquently, we need to update our @@ -1009,6 +1028,8 @@ void RuntimeDyldImpl::resolveExternalSymbols() { ExternalSymbolRelocations.erase(i); } + + return Error::success(); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index e45fdc7aee1..5bc7434e703 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -742,7 +742,7 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const { uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { if (auto InternalSymbol = getRTDyld().getSymbol(Symbol)) return InternalSymbol.getAddress(); - return getRTDyld().Resolver.findSymbol(Symbol).getAddress(); + return cantFail(getRTDyld().Resolver.findSymbol(Symbol).getAddress()); } uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 5268bc5a186..95b04fd9325 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -417,7 +417,7 @@ protected: StubMap &Stubs) = 0; /// \brief Resolve relocations to external symbols. - void resolveExternalSymbols(); + Error resolveExternalSymbols(); // \brief Compute an upper bound of the memory that is required to load all // sections diff --git a/llvm/tools/lli/OrcLazyJIT.cpp b/llvm/tools/lli/OrcLazyJIT.cpp index 2e15894152f..f1a752e0790 100644 --- a/llvm/tools/lli/OrcLazyJIT.cpp +++ b/llvm/tools/lli/OrcLazyJIT.cpp @@ -148,18 +148,19 @@ int llvm::runOrcLazyJIT(std::vector<std::unique_ptr<Module>> Ms, // Add the module, look up main and run it. for (auto &M : Ms) - J.addModule(std::shared_ptr<Module>(std::move(M))); - auto MainSym = J.findSymbol("main"); - - if (!MainSym) { + cantFail(J.addModule(std::shared_ptr<Module>(std::move(M)))); + + if (auto MainSym = J.findSymbol("main")) { + typedef int (*MainFnPtr)(int, const char*[]); + std::vector<const char *> ArgV; + for (auto &Arg : Args) + ArgV.push_back(Arg.c_str()); + auto Main = fromTargetAddress<MainFnPtr>(cantFail(MainSym.getAddress())); + return Main(ArgV.size(), (const char**)ArgV.data()); + } else if (auto Err = MainSym.takeError()) + logAllUnhandledErrors(std::move(Err), llvm::errs(), ""); + else errs() << "Could not find main function.\n"; - return 1; - } - using MainFnPtr = int (*)(int, const char*[]); - std::vector<const char *> ArgV; - for (auto &Arg : Args) - ArgV.push_back(Arg.c_str()); - auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress()); - return Main(ArgV.size(), (const char**)ArgV.data()); + return 1; } diff --git a/llvm/tools/lli/OrcLazyJIT.h b/llvm/tools/lli/OrcLazyJIT.h index 5592fb65139..47a2acc4d7e 100644 --- a/llvm/tools/lli/OrcLazyJIT.h +++ b/llvm/tools/lli/OrcLazyJIT.h @@ -75,10 +75,14 @@ public: CXXRuntimeOverrides.runDestructors(); // Run any IR destructors. for (auto &DtorRunner : IRStaticDestructorRunners) - DtorRunner.runViaLayer(CODLayer); + if (auto Err = DtorRunner.runViaLayer(CODLayer)) { + // FIXME: OrcLazyJIT should probably take a "shutdownError" callback to + // report these errors on. + report_fatal_error(std::move(Err)); + } } - void addModule(std::shared_ptr<Module> M) { + Error addModule(std::shared_ptr<Module> M) { if (M->getDataLayout().isDefault()) M->setDataLayout(DL); @@ -125,19 +129,27 @@ public: ); // Add the module to the JIT. - ModulesHandle = - CODLayer.addModule(std::move(M), std::move(Resolver)); + if (auto ModulesHandleOrErr = + CODLayer.addModule(std::move(M), std::move(Resolver))) + ModulesHandle = std::move(*ModulesHandleOrErr); + else + return ModulesHandleOrErr.takeError(); + } else - CODLayer.addExtraModule(ModulesHandle, std::move(M)); + if (auto Err = CODLayer.addExtraModule(ModulesHandle, std::move(M))) + return Err; // Run the static constructors, and save the static destructor runner for // execution when the JIT is torn down. orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), ModulesHandle); - CtorRunner.runViaLayer(CODLayer); + if (auto Err = CtorRunner.runViaLayer(CODLayer)) + return Err; IRStaticDestructorRunners.emplace_back(std::move(DtorNames), ModulesHandle); + + return Error::success(); } JITSymbol findSymbol(const std::string &Name) { diff --git a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp index 13693381c00..844746f28c0 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp @@ -50,13 +50,14 @@ public: TEST(CompileOnDemandLayerTest, FindSymbol) { auto MockBaseLayer = createMockBaseLayer<int>( - DoNothingAndReturn<int>(0), DoNothingAndReturn<void>(), + DoNothingAndReturn<int>(0), + [](int Handle) { return Error::success(); }, [](const std::string &Name, bool) { if (Name == "foo") return JITSymbol(1, JITSymbolFlags::Exported); return JITSymbol(nullptr); }, - DoNothingAndReturn<JITSymbol>(nullptr)); + ReturnNullJITSymbol()); typedef decltype(MockBaseLayer) MockBaseLayerT; DummyCallbackManager CallbackMgr; diff --git a/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp index 630f127b392..2756999c216 100644 --- a/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp @@ -37,13 +37,15 @@ TEST(GlobalMappingLayerTest, Empty) { // Test fall-through for symbol in base layer. auto BarSym = L.findSymbol("bar", true); - EXPECT_EQ(BarSym.getAddress(), static_cast<JITTargetAddress>(0x4567)) + EXPECT_EQ(cantFail(BarSym.getAddress()), + static_cast<JITTargetAddress>(0x4567)) << "Symbol lookup fall-through failed."; // Test setup of a global mapping. L.setGlobalMapping("foo", 0x0123); auto FooSym2 = L.findSymbol("foo", true); - EXPECT_EQ(FooSym2.getAddress(), static_cast<JITTargetAddress>(0x0123)) + EXPECT_EQ(cantFail(FooSym2.getAddress()), + static_cast<JITTargetAddress>(0x0123)) << "Symbol mapping setup failed."; // Test removal of a global mapping. diff --git a/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp index 26d13e2dbc6..0dba66d4753 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp @@ -27,7 +27,7 @@ struct MockBaseLayer { TEST(LazyEmittingLayerTest, Empty) { MockBaseLayer M; llvm::orc::LazyEmittingLayer<MockBaseLayer> L(M); - L.addModule(std::unique_ptr<llvm::Module>(), nullptr); + cantFail(L.addModule(std::unique_ptr<llvm::Module>(), nullptr)); } } diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp index 6671442db42..25103f79ac6 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp @@ -50,8 +50,9 @@ public: MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); } template <typename ObjPtrT> - ObjHandleT addObject(ObjPtrT Obj, - std::shared_ptr<llvm::JITSymbolResolver> Resolver) { + llvm::Expected<ObjHandleT> + addObject(ObjPtrT Obj, + std::shared_ptr<llvm::JITSymbolResolver> Resolver) { EXPECT_EQ(MockResolver, Resolver) << "Resolver should pass through"; EXPECT_EQ(MockObject + 1, *Obj) << "Transform should be applied"; LastCalled = "addObject"; @@ -73,10 +74,12 @@ public: resetExpectations(); } - void removeObject(ObjHandleT H) { + llvm::Error removeObject(ObjHandleT H) { EXPECT_EQ(MockObjHandle, H); LastCalled = "removeObject"; + return llvm::Error::success(); } + void expectRemoveObject(ObjHandleT H) { MockObjHandle = H; } void verifyRemoveObject() { EXPECT_EQ("removeObject", LastCalled); @@ -89,7 +92,7 @@ public: EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through"; LastCalled = "findSymbol"; MockSymbol = llvm::JITSymbol(122, llvm::JITSymbolFlags::None); - return MockSymbol; + return llvm::JITSymbol(122, llvm::JITSymbolFlags::None); } void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) { MockName = Name; @@ -97,7 +100,8 @@ public: } void verifyFindSymbol(llvm::JITSymbol Returned) { EXPECT_EQ("findSymbol", LastCalled); - EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress()) + EXPECT_EQ(cantFail(MockSymbol.getAddress()), + cantFail(Returned.getAddress())) << "Return should pass through"; resetExpectations(); } @@ -109,7 +113,7 @@ public: EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through"; LastCalled = "findSymbolIn"; MockSymbol = llvm::JITSymbol(122, llvm::JITSymbolFlags::None); - return MockSymbol; + return llvm::JITSymbol(122, llvm::JITSymbolFlags::None); } void expectFindSymbolIn(ObjHandleT H, const std::string &Name, bool ExportedSymbolsOnly) { @@ -119,16 +123,20 @@ public: } void verifyFindSymbolIn(llvm::JITSymbol Returned) { EXPECT_EQ("findSymbolIn", LastCalled); - EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress()) + EXPECT_EQ(cantFail(MockSymbol.getAddress()), + cantFail(Returned.getAddress())) << "Return should pass through"; resetExpectations(); } - void emitAndFinalize(ObjHandleT H) { + llvm::Error emitAndFinalize(ObjHandleT H) { EXPECT_EQ(MockObjHandle, H) << "Handle should pass through"; LastCalled = "emitAndFinalize"; + return llvm::Error::success(); } + void expectEmitAndFinalize(ObjHandleT H) { MockObjHandle = H; } + void verifyEmitAndFinalize() { EXPECT_EQ("emitAndFinalize", LastCalled); resetExpectations(); @@ -201,38 +209,38 @@ TEST(ObjectTransformLayerTest, Main) { auto Obj1 = std::make_shared<MockObjectFile>(211); auto SR = std::make_shared<NullResolver>(); M.expectAddObject(Obj1, SR); - auto H = T1.addObject(std::move(Obj1), SR); + auto H = cantFail(T1.addObject(std::move(Obj1), SR)); M.verifyAddObject(H); // Test addObjectSet with T2 (mutating) auto Obj2 = std::make_shared<MockObjectFile>(222); M.expectAddObject(Obj2, SR); - H = T2.addObject(Obj2, SR); + H = cantFail(T2.addObject(Obj2, SR)); M.verifyAddObject(H); EXPECT_EQ(223, *Obj2) << "Expected mutation"; // Test removeObjectSet M.expectRemoveObject(H); - T1.removeObject(H); + cantFail(T1.removeObject(H)); M.verifyRemoveObject(); // Test findSymbol std::string Name = "foo"; bool ExportedOnly = true; M.expectFindSymbol(Name, ExportedOnly); - llvm::JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly); - M.verifyFindSymbol(Symbol); + llvm::JITSymbol Sym1 = T2.findSymbol(Name, ExportedOnly); + M.verifyFindSymbol(std::move(Sym1)); // Test findSymbolIn Name = "bar"; ExportedOnly = false; M.expectFindSymbolIn(H, Name, ExportedOnly); - Symbol = T1.findSymbolIn(H, Name, ExportedOnly); - M.verifyFindSymbolIn(Symbol); + llvm::JITSymbol Sym2 = T1.findSymbolIn(H, Name, ExportedOnly); + M.verifyFindSymbolIn(std::move(Sym2)); // Test emitAndFinalize M.expectEmitAndFinalize(H); - T2.emitAndFinalize(H); + cantFail(T2.emitAndFinalize(H)); M.verifyEmitAndFinalize(); // Test mapSectionAddress @@ -305,15 +313,15 @@ TEST(ObjectTransformLayerTest, Main) { // Make sure that the calls from IRCompileLayer to ObjectTransformLayer // compile. auto Resolver = std::make_shared<NullResolver>(); - CompileLayer.addModule(std::shared_ptr<llvm::Module>(), Resolver); + cantFail(CompileLayer.addModule(std::shared_ptr<llvm::Module>(), Resolver)); // Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer // compile. decltype(TransformLayer)::ObjHandleT H2; - TransformLayer.emitAndFinalize(H2); + cantFail(TransformLayer.emitAndFinalize(H2)); TransformLayer.findSymbolIn(H2, Name, false); TransformLayer.findSymbol(Name, true); TransformLayer.mapSectionAddress(H2, nullptr, 0); - TransformLayer.removeObject(H2); + cantFail(TransformLayer.removeObject(H2)); } } diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp index 2900a9c9276..5a4d6b4a225 100644 --- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp @@ -66,10 +66,11 @@ protected: auto *ET = CCtx->APIExecTest; CCtx->M = ET->createTestModule(ET->TM->getTargetTriple()); LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(CCtx->M.release())); - CCtx->H = LLVMOrcAddEagerlyCompiledIR(JITStack, SM, myResolver, nullptr); + LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, SM, myResolver, nullptr); LLVMOrcDisposeSharedModuleRef(SM); CCtx->Compiled = true; - LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main"); + LLVMOrcTargetAddress MainAddr; + LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main"); LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr); return MainAddr; } @@ -89,10 +90,12 @@ TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) { LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release())); - LLVMOrcModuleHandle H = - LLVMOrcAddEagerlyCompiledIR(JIT, SM, myResolver, nullptr); + LLVMOrcModuleHandle H; + LLVMOrcAddEagerlyCompiledIR(JIT, &H, SM, myResolver, nullptr); LLVMOrcDisposeSharedModuleRef(SM); - MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main"); + LLVMOrcTargetAddress MainAddr; + LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main"); + MainFnTy MainFn = (MainFnTy)MainAddr; int Result = MainFn(); EXPECT_EQ(Result, 42) << "Eagerly JIT'd code did not return expected result"; @@ -115,10 +118,12 @@ TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) { LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release())); - LLVMOrcModuleHandle H = - LLVMOrcAddLazilyCompiledIR(JIT, SM, myResolver, nullptr); + LLVMOrcModuleHandle H; + LLVMOrcAddLazilyCompiledIR(JIT, &H, SM, myResolver, nullptr); LLVMOrcDisposeSharedModuleRef(SM); - MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main"); + LLVMOrcTargetAddress MainAddr; + LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main"); + MainFnTy MainFn = (MainFnTy)MainAddr; int Result = MainFn(); EXPECT_EQ(Result, 42) << "Lazily JIT'd code did not return expected result"; @@ -140,11 +145,12 @@ TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) { CompileContext C; C.APIExecTest = this; - LLVMOrcCreateIndirectStub(JIT, "foo", - LLVMOrcCreateLazyCompileCallback(JIT, - myCompileCallback, - &C)); - MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo"); + LLVMOrcTargetAddress CCAddr; + LLVMOrcCreateLazyCompileCallback(JIT, &CCAddr, myCompileCallback, &C); + LLVMOrcCreateIndirectStub(JIT, "foo", CCAddr); + LLVMOrcTargetAddress MainAddr; + LLVMOrcGetSymbolAddress(JIT, &MainAddr, "foo"); + MainFnTy FooFn = (MainFnTy)MainAddr; int Result = FooFn(); EXPECT_TRUE(C.Compiled) << "Function wasn't lazily compiled"; diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h index d7049ef00e6..6c6b4918c20 100644 --- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h +++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -119,19 +119,21 @@ public: RemoveModuleFtor &&RemoveModule, FindSymbolFtor &&FindSymbol, FindSymbolInFtor &&FindSymbolIn) - : AddModule(AddModule), RemoveModule(RemoveModule), - FindSymbol(FindSymbol), FindSymbolIn(FindSymbolIn) + : AddModule(std::move(AddModule)), + RemoveModule(std::move(RemoveModule)), + FindSymbol(std::move(FindSymbol)), + FindSymbolIn(std::move(FindSymbolIn)) {} template <typename ModuleT, typename MemoryManagerPtrT, typename SymbolResolverPtrT> - ModuleHandleT addModule(ModuleT Ms, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver) { + Expected<ModuleHandleT> addModule(ModuleT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { return AddModule(std::move(Ms), std::move(MemMgr), std::move(Resolver)); } - void removeModule(ModuleHandleT H) { - RemoveModule(H); + Error removeModule(ModuleHandleT H) { + return RemoveModule(H); } JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { @@ -169,15 +171,24 @@ createMockBaseLayer(AddModuleFtor &&AddModule, std::forward<FindSymbolInFtor>(FindSymbolIn)); } + +class ReturnNullJITSymbol { +public: + template <typename... Args> + JITSymbol operator()(Args...) const { + return nullptr; + } +}; + template <typename ReturnT> class DoNothingAndReturn { public: - DoNothingAndReturn(ReturnT Val) : Val(Val) {} + DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {} template <typename... Args> - ReturnT operator()(Args...) const { return Val; } + void operator()(Args...) const { return Ret; } private: - ReturnT Val; + ReturnT Ret; }; template <> diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index 383ce8fe54c..e4b61d855c5 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -103,21 +103,21 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { { // Test with ProcessAllSections = false (the default). - auto H = ObjLayer.addObject(Obj, Resolver); - ObjLayer.emitAndFinalize(H); + auto H = cantFail(ObjLayer.addObject(Obj, Resolver)); + cantFail(ObjLayer.emitAndFinalize(H)); EXPECT_EQ(DebugSectionSeen, false) << "Unexpected debug info section"; - ObjLayer.removeObject(H); + cantFail(ObjLayer.removeObject(H)); } { // Test with ProcessAllSections = true. ObjLayer.setProcessAllSections(true); - auto H = ObjLayer.addObject(Obj, Resolver); - ObjLayer.emitAndFinalize(H); + auto H = cantFail(ObjLayer.addObject(Obj, Resolver)); + cantFail(ObjLayer.emitAndFinalize(H)); EXPECT_EQ(DebugSectionSeen, true) << "Expected debug info section not seen"; - ObjLayer.removeObject(H); + cantFail(ObjLayer.removeObject(H)); } } @@ -181,11 +181,11 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { return JITSymbol(nullptr); }); - ObjLayer.addObject(std::move(Obj1), Resolver); - auto H = ObjLayer.addObject(std::move(Obj2), Resolver); - ObjLayer.emitAndFinalize(H); - ObjLayer.removeObject(H); - + cantFail(ObjLayer.addObject(std::move(Obj1), Resolver)); + auto H = cantFail(ObjLayer.addObject(std::move(Obj2), Resolver)); + cantFail(ObjLayer.emitAndFinalize(H)); + cantFail(ObjLayer.removeObject(H)); + // Finalization of module 2 should trigger finalization of module 1. // Verify that finalize on SMMW is only called once. EXPECT_EQ(MM->FinalizationCount, 1) @@ -244,11 +244,11 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { Compile(*MB2.getModule())); auto NR = std::make_shared<NullResolver>(); - auto H = ObjLayer.addObject(std::move(Obj1), NR); - ObjLayer.addObject(std::move(Obj2), NR); - ObjLayer.emitAndFinalize(H); - ObjLayer.removeObject(H); - + auto H = cantFail(ObjLayer.addObject(std::move(Obj1), NR)); + cantFail(ObjLayer.addObject(std::move(Obj2), NR)); + cantFail(ObjLayer.emitAndFinalize(H)); + cantFail(ObjLayer.removeObject(H)); + // Only one call to needsToReserveAllocationSpace should have been made. EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1) << "More than one call to needsToReserveAllocationSpace " |