diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index f31b97ad762..c5fc9bdb4d0 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -149,6 +149,11 @@ uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); 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/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 9b41ed4391c..2562da7cf60 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -158,6 +158,8 @@ protected: /// 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 @@ public: /// 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/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index ff1e8050c7e..addec6871fa 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -308,6 +308,18 @@ uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) { 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/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 9c3d0d53984..d2af987946e 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -239,6 +239,10 @@ void MCJIT::finalizeLoadedModules() { // 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