diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h index c02975730ba..c0b627e60b9 100644 --- a/include/llvm/ExecutionEngine/Orc/JITSymbol.h +++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h @@ -28,10 +28,25 @@ class JITSymbol { public: typedef std::function GetAddressFtor; + /// @brief Create a 'null' symbol that represents failure to find a symbol + /// definition. JITSymbol(std::nullptr_t) : CachedAddr(0) {} + /// @brief Create a symbol for a definition with a known address. + JITSymbol(TargetAddress Addr) + : CachedAddr(Addr) {} + + /// @brief Create a symbol for a definition that doesn't have a known address + /// yet. + /// @param GetAddress A functor to materialize a definition (fixing the + /// address) on demand. + /// + /// This constructor allows a JIT layer to provide a reference to a symbol + /// definition without actually materializing the definition up front. The + /// user can materialize the definition at any time by calling the getAddress + /// method. JITSymbol(GetAddressFtor GetAddress) - : CachedAddr(0), GetAddress(std::move(GetAddress)) {} + : CachedAddr(0), GetAddress(std::move(GetAddress)) {} /// @brief Returns true if the symbol exists, false otherwise. explicit operator bool() const { return CachedAddr || GetAddress; } diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 4dcb3808dab..ad7c9ebdd9b 100644 --- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -213,16 +213,27 @@ public: /// given object set. JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, bool ExportedSymbolsOnly) { - if (auto Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) - return JITSymbol( - [this, Addr, H](){ - if (H->NeedsFinalization()) { - H->Finalize(); - if (NotifyFinalized) - NotifyFinalized(H); - } - return Addr; - }); + if (auto Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) { + if (!H->NeedsFinalization()) { + // If this instance has already been finalized then we can just return + // the address. + return JITSymbol(Addr); + } else { + // If this instance needs finalization return a functor that will do it. + // The functor still needs to double-check whether finalization is + // required, in case someone else finalizes this set before the functor + // is called. + return JITSymbol( + [this, Addr, H]() { + if (H->NeedsFinalization()) { + H->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + return Addr; + }); + } + } return nullptr; }