orc::SymbolResolver to JITSymbolResolver adapter.
The new orc::SymbolResolver interface uses asynchronous queries for better
performance. (Asynchronous queries with bulk lookup minimize RPC/IPC overhead,
support parallel incoming queries, and expose more available work for
distribution). Existing ORC layers will soon be updated to use the
orc::SymbolResolver API rather than the legacy llvm::JITSymbolResolver API.
Because RuntimeDyld still uses JITSymbolResolver, this patch also includes an
adapter that wraps an orc::SymbolResolver with a JITSymbolResolver API.
llvm-svn: 323073
/// remote JITing, and expose opportunities for parallel compilation.
class JITSymbolResolver {
public:
- using SymbolNameSet = std::set<StringRef>;
+ using LookupSet = std::set<StringRef>;
using LookupResult = std::map<StringRef, JITEvaluatedSymbol>;
using LookupFlagsResult = std::map<StringRef, JITSymbolFlags>;
///
/// This method will return an error if any of the given symbols can not be
/// resolved, or if the resolution process itself triggers an error.
- virtual Expected<LookupResult> lookup(const SymbolNameSet &Symbols) = 0;
+ virtual Expected<LookupResult> lookup(const LookupSet &Symbols) = 0;
/// @brief Returns the symbol flags for each of the given symbols.
///
/// This method does NOT return an error if any of the given symbols is
/// missing. Instead, that symbol will be left out of the result map.
- virtual Expected<LookupFlagsResult>
- lookupFlags(const SymbolNameSet &Symbols) = 0;
+ virtual Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) = 0;
private:
virtual void anchor();
/// @brief Performs lookup by, for each symbol, first calling
/// findSymbolInLogicalDylib and if that fails calling
/// findSymbol.
- Expected<LookupResult> lookup(const SymbolNameSet &Symbols) final;
+ Expected<LookupResult> lookup(const LookupSet &Symbols) final;
/// @brief Performs flags lookup by calling findSymbolInLogicalDylib and
/// returning the flags value for that symbol.
- Expected<LookupFlagsResult> lookupFlags(const SymbolNameSet &Symbols) final;
+ Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) final;
/// This method returns the address of the specified symbol if it exists
/// within the logical dynamic library represented by this JITSymbolResolver.
SymbolsReadyCallback NotifySymbolsReady;
};
+/// @brief A SymbolFlagsMap containing flags of found symbols, plus a set of
+/// not-found symbols. Shared between SymbolResolver::lookupFlags and
+/// VSO::lookupFlags for convenience.
+struct LookupFlagsResult {
+ SymbolFlagsMap SymbolFlags;
+ SymbolNameSet SymbolsNotFound;
+};
+
+class SymbolResolver {
+public:
+ virtual ~SymbolResolver() = default;
+ virtual LookupFlagsResult lookupFlags(const SymbolNameSet &Symbols) = 0;
+ virtual SymbolNameSet lookup(AsynchronousSymbolQuery &Query,
+ SymbolNameSet Symbols) = 0;
+
+private:
+ virtual void anchor();
+};
+
/// @brief Represents a source of symbol definitions which may be materialized
/// (turned into data / code through some materialization process) or
/// discarded (if the definition is overridden by a stronger one).
std::map<SymbolStringPtr, RelativeLinkageStrength>;
using SourceWorkMap = std::map<SymbolSource *, SymbolNameSet>;
- struct LookupFlagsResult {
- SymbolFlagsMap SymbolFlags;
- SymbolNameSet SymbolsNotFound;
- };
-
struct LookupResult {
SourceWorkMap MaterializationWork;
SymbolNameSet UnresolvedSymbols;
/// @brief An ExecutionSession represents a running JIT program.
class ExecutionSession {
public:
+ /// @brief Construct an ExecutionEngine.
+ ///
+ /// SymbolStringPools may be shared between ExecutionSessions.
+ ExecutionSession(SymbolStringPool &SSP);
+
+ /// @brief Returns the SymbolStringPool for this ExecutionSession.
+ SymbolStringPool &getSymbolStringPool() const { return SSP; }
+
/// @brief Allocate a module key for a new module to add to the JIT.
VModuleKey allocateVModule();
void releaseVModule(VModuleKey Key);
public:
+ SymbolStringPool &SSP;
VModuleKey LastKey = 0;
};
--- /dev/null
+//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains core ORC APIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
+#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
+
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+
+namespace llvm {
+namespace orc {
+
+class JITSymbolResolverAdapter : public JITSymbolResolver {
+public:
+ JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R);
+ Expected<LookupResult> lookup(const LookupSet &Symbols) override;
+ Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
+
+private:
+ ExecutionSession &ES;
+ std::set<SymbolStringPtr> ResolvedStrings;
+ SymbolResolver &R;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H
Core.cpp
ExecutionUtils.cpp
IndirectionUtils.cpp
+ Legacy.cpp
NullResolver.cpp
OrcABISupport.cpp
OrcCBindings.cpp
namespace llvm {
namespace orc {
+void SymbolResolver::anchor() {}
void SymbolSource::anchor() {}
AsynchronousSymbolQuery::AsynchronousSymbolQuery(
}
}
-VSO::LookupFlagsResult VSO::lookupFlags(SymbolNameSet Names) {
+LookupFlagsResult VSO::lookupFlags(SymbolNameSet Names) {
SymbolFlagsMap FlagsFound;
for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
return {std::move(MaterializationWork), std::move(Names)};
}
+ExecutionSession::ExecutionSession(SymbolStringPool &SSP) : SSP(SSP) {}
+
VModuleKey ExecutionSession::allocateVModule() { return ++LastKey; }
void ExecutionSession::releaseVModule(VModuleKey VMod) {
--- /dev/null
+//===------- Legacy.cpp - Adapters for ExecutionEngine API interop --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
+
+namespace llvm {
+namespace orc {
+
+JITSymbolResolverAdapter::JITSymbolResolverAdapter(ExecutionSession &ES,
+ SymbolResolver &R)
+ : ES(ES), R(R) {}
+
+Expected<JITSymbolResolverAdapter::LookupResult>
+JITSymbolResolverAdapter::lookup(const LookupSet &Symbols) {
+ Error Err = Error::success();
+ JITSymbolResolver::LookupResult Result;
+
+ SymbolNameSet InternedSymbols;
+ for (auto &S : Symbols)
+ InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
+
+ auto OnResolve = [&](Expected<SymbolMap> R) {
+ if (R) {
+ for (auto &KV : *R) {
+ ResolvedStrings.insert(KV.first);
+ Result[*KV.first] = KV.second;
+ }
+ } else
+ Err = joinErrors(std::move(Err), R.takeError());
+ };
+
+ auto OnReady = [](Error Err) {
+ // FIXME: Report error to ExecutionSession.
+ logAllUnhandledErrors(std::move(Err), errs(),
+ "legacy resolver received on-ready error:\n");
+ };
+
+ AsynchronousSymbolQuery Query(InternedSymbols, OnResolve, OnReady);
+
+ auto UnresolvedSymbols = R.lookup(Query, InternedSymbols);
+
+ if (!UnresolvedSymbols.empty())
+ Err = joinErrors(std::move(Err),
+ make_error<StringError>("Unresolved symbols",
+ inconvertibleErrorCode()));
+
+ if (Err)
+ return std::move(Err);
+
+ return Result;
+}
+
+Expected<JITSymbolResolverAdapter::LookupFlagsResult>
+JITSymbolResolverAdapter::lookupFlags(const LookupSet &Symbols) {
+ SymbolNameSet InternedSymbols;
+ for (auto &S : Symbols)
+ InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
+
+ LookupFlagsResult Result;
+ for (auto &KV : R.lookupFlags(InternedSymbols).SymbolFlags) {
+ ResolvedStrings.insert(KV.first);
+ Result[*KV.first] = KV.second;
+ }
+
+ return Result;
+}
+
+} // End namespace orc.
+} // End namespace llvm.
/// findSymbolInLogicalDylib and if that fails calling
/// findSymbol.
Expected<JITSymbolResolver::LookupResult>
-LegacyJITSymbolResolver::lookup(const SymbolNameSet &Symbols) {
+LegacyJITSymbolResolver::lookup(const LookupSet &Symbols) {
JITSymbolResolver::LookupResult Result;
for (auto &Symbol : Symbols) {
std::string SymName = Symbol.str();
/// @brief Performs flags lookup by calling findSymbolInLogicalDylib and
/// returning the flags value for that symbol.
Expected<JITSymbolResolver::LookupFlagsResult>
-LegacyJITSymbolResolver::lookupFlags(const SymbolNameSet &Symbols) {
+LegacyJITSymbolResolver::lookupFlags(const LookupSet &Symbols) {
JITSymbolResolver::LookupFlagsResult Result;
for (auto &Symbol : Symbols) {
// definitions occur elsewhere.
JITSymbolResolver::LookupFlagsResult SymbolFlags;
{
- JITSymbolResolver::SymbolNameSet Symbols;
+ JITSymbolResolver::LookupSet Symbols;
for (auto &Sym : Obj.symbols()) {
uint32_t Flags = Sym.getFlags();
if ((Flags & SymbolRef::SF_Common) || (Flags & SymbolRef::SF_Weak)) {
// Resolution can trigger emission of more symbols, so iterate until
// we've resolved *everything*.
{
- JITSymbolResolver::SymbolNameSet ResolvedSymbols;
+ JITSymbolResolver::LookupSet ResolvedSymbols;
while (true) {
- JITSymbolResolver::SymbolNameSet NewSymbols;
+ JITSymbolResolver::LookupSet NewSymbols;
for (auto &RelocKV : ExternalSymbolRelocations) {
StringRef Name = RelocKV.first();
bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
if (getRTDyld().getSymbol(Symbol))
return true;
- JITSymbolResolver::SymbolNameSet Symbols({Symbol});
+ JITSymbolResolver::LookupSet Symbols({Symbol});
auto Result = getRTDyld().Resolver.lookup(Symbols);
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
return InternalSymbol.getAddress();
- JITSymbolResolver::SymbolNameSet Symbols({Symbol});
+ JITSymbolResolver::LookupSet Symbols({Symbol});
auto Result = getRTDyld().Resolver.lookup(Symbols);
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
IndirectionUtilsTest.cpp
GlobalMappingLayerTest.cpp
LazyEmittingLayerTest.cpp
+ LegacyAPIInteropTest.cpp
ObjectTransformLayerTest.cpp
OrcCAPITest.cpp
OrcTestCommon.cpp
--- /dev/null
+//===----------- CoreAPIsTest.cpp - Unit tests for Core ORC APIs ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+class SimpleORCResolver : public SymbolResolver {
+public:
+ using LookupFlagsFn = std::function<LookupFlagsResult(const SymbolNameSet &)>;
+ using LookupFn = std::function<SymbolNameSet(AsynchronousSymbolQuery &Q,
+ SymbolNameSet Symbols)>;
+
+ SimpleORCResolver(LookupFlagsFn LookupFlags, LookupFn Lookup)
+ : LookupFlags(std::move(LookupFlags)), Lookup(std::move(Lookup)) {}
+
+ LookupFlagsResult lookupFlags(const SymbolNameSet &Symbols) override {
+ return LookupFlags(Symbols);
+ }
+
+ SymbolNameSet lookup(AsynchronousSymbolQuery &Query,
+ SymbolNameSet Symbols) override {
+ return Lookup(Query, std::move(Symbols));
+ };
+
+private:
+ LookupFlagsFn LookupFlags;
+ LookupFn Lookup;
+};
+
+namespace {
+
+TEST(LegacyAPIInteropTest, QueryAgainstVSO) {
+
+ SymbolStringPool SP;
+ ExecutionSession ES(SP);
+ auto Foo = SP.intern("foo");
+
+ VSO V;
+ SymbolMap Defs;
+ JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported);
+ Defs[Foo] = FooSym;
+ cantFail(V.define(std::move(Defs)));
+
+ auto LookupFlags = [&](const SymbolNameSet &Names) {
+ return V.lookupFlags(Names);
+ };
+
+ auto Lookup = [&](AsynchronousSymbolQuery &Query, SymbolNameSet Symbols) {
+ auto R = V.lookup(Query, Symbols);
+ EXPECT_TRUE(R.MaterializationWork.empty())
+ << "Query resulted in unexpected materialization work";
+ return std::move(R.UnresolvedSymbols);
+ };
+
+ SimpleORCResolver UnderlyingResolver(std::move(LookupFlags),
+ std::move(Lookup));
+ JITSymbolResolverAdapter Resolver(ES, UnderlyingResolver);
+
+ JITSymbolResolver::LookupSet Names{StringRef("foo")};
+
+ auto LFR = Resolver.lookupFlags(Names);
+ EXPECT_TRUE(!!LFR) << "lookupFlags failed";
+ EXPECT_EQ(LFR->size(), 1U)
+ << "lookupFlags returned the wrong number of results";
+ EXPECT_EQ(LFR->count(*Foo), 1U)
+ << "lookupFlags did not contain a result for 'foo'";
+ EXPECT_EQ((*LFR)[*Foo], FooSym.getFlags())
+ << "lookupFlags contained the wrong result for 'foo'";
+
+ auto LR = Resolver.lookup(Names);
+ EXPECT_TRUE(!!LR) << "lookup failed";
+ EXPECT_EQ(LR->size(), 1U) << "lookup returned the wrong number of results";
+ EXPECT_EQ(LR->count(*Foo), 1U) << "lookup did not contain a result for 'foo'";
+ EXPECT_EQ((*LR)[*Foo].getFlags(), FooSym.getFlags())
+ << "lookup returned the wrong result for flags of 'foo'";
+ EXPECT_EQ((*LR)[*Foo].getAddress(), FooSym.getAddress())
+ << "lookup returned the wrong result for address of 'foo'";
+}
+
+} // namespace