diff --git a/llvm/include/llvm-c/ExecutionEngine.h b/llvm/include/llvm-c/ExecutionEngine.h --- a/llvm/include/llvm-c/ExecutionEngine.h +++ b/llvm/include/llvm-c/ExecutionEngine.h @@ -149,6 +149,11 @@ uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); +/// Returns true on error, false on success. If true is returned then the error +/// message is copied to OutStr and cleared in the ExecutionEngine instance. +LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, + char **OutError); + /*===-- Operations on memory managers -------------------------------------===*/ typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( diff --git a/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h --- a/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -158,6 +158,8 @@ /// getMangledName - Get mangled name. std::string getMangledName(const GlobalValue *GV); + std::string ErrMsg; + public: /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must /// be held while changing the internal state of any of those classes. @@ -275,8 +277,20 @@ /// object have been relocated using mapSectionAddress. When this method is /// called the MCJIT execution engine will reapply relocations for a loaded /// object. This method has no effect for the interpeter. + /// + /// Returns true on success, false on failure. Error messages can be retrieved + /// by calling getError(); virtual void finalizeObject() {} + /// Returns true if an error has been recorded. + bool hasError() const { return !ErrMsg.empty(); } + + /// Clear the error message. + void clearErrorMessage() { ErrMsg.clear(); } + + /// Returns the most recent error message. + const std::string &getErrorMessage() const { return ErrMsg; } + /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a program. /// diff --git a/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp --- a/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -308,6 +308,18 @@ return unwrap(EE)->getFunctionAddress(Name); } +LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, + char **OutError) { + assert(OutError && "OutError must be non-null"); + auto *ExecEngine = unwrap(EE); + if (ExecEngine->hasError()) { + *OutError = strdup(ExecEngine->getErrorMessage().c_str()); + ExecEngine->clearErrorMessage(); + return true; + } + return false; +} + /*===-- Operations on memory managers -------------------------------------===*/ namespace { diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp --- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -239,6 +239,10 @@ // Resolve any outstanding relocations. Dyld.resolveRelocations(); + // Check for Dyld error. + if (Dyld.hasError()) + ErrMsg = Dyld.getErrorString().str(); + OwnedModules.markAllLoadedModulesAsFinalized(); // Register EH frame data for any module we own which has been loaded