mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 00:16:25 +00:00
[ORC] Add orc::SymbolResolver, a Orc/Legacy API interop header, and an
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
This commit is contained in:
parent
0bc28ea370
commit
5020662a41
@ -285,7 +285,7 @@ private:
|
||||
/// 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>;
|
||||
|
||||
@ -296,14 +296,13 @@ public:
|
||||
///
|
||||
/// 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();
|
||||
@ -315,11 +314,11 @@ public:
|
||||
/// @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.
|
||||
|
@ -92,6 +92,25 @@ private:
|
||||
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).
|
||||
@ -138,11 +157,6 @@ public:
|
||||
std::map<SymbolStringPtr, RelativeLinkageStrength>;
|
||||
using SourceWorkMap = std::map<SymbolSource *, SymbolNameSet>;
|
||||
|
||||
struct LookupFlagsResult {
|
||||
SymbolFlagsMap SymbolFlags;
|
||||
SymbolNameSet SymbolsNotFound;
|
||||
};
|
||||
|
||||
struct LookupResult {
|
||||
SourceWorkMap MaterializationWork;
|
||||
SymbolNameSet UnresolvedSymbols;
|
||||
@ -245,6 +259,14 @@ private:
|
||||
/// @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();
|
||||
|
||||
@ -254,6 +276,7 @@ public:
|
||||
void releaseVModule(VModuleKey Key);
|
||||
|
||||
public:
|
||||
SymbolStringPool &SSP;
|
||||
VModuleKey LastKey = 0;
|
||||
};
|
||||
|
||||
|
38
include/llvm/ExecutionEngine/Orc/Legacy.h
Normal file
38
include/llvm/ExecutionEngine/Orc/Legacy.h
Normal file
@ -0,0 +1,38 @@
|
||||
//===--- 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
|
@ -2,6 +2,7 @@ add_llvm_library(LLVMOrcJIT
|
||||
Core.cpp
|
||||
ExecutionUtils.cpp
|
||||
IndirectionUtils.cpp
|
||||
Legacy.cpp
|
||||
NullResolver.cpp
|
||||
OrcABISupport.cpp
|
||||
OrcCBindings.cpp
|
||||
|
@ -13,6 +13,7 @@
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
void SymbolResolver::anchor() {}
|
||||
void SymbolSource::anchor() {}
|
||||
|
||||
AsynchronousSymbolQuery::AsynchronousSymbolQuery(
|
||||
@ -287,7 +288,7 @@ void VSO::finalize(SymbolNameSet SymbolsToFinalize) {
|
||||
}
|
||||
}
|
||||
|
||||
VSO::LookupFlagsResult VSO::lookupFlags(SymbolNameSet Names) {
|
||||
LookupFlagsResult VSO::lookupFlags(SymbolNameSet Names) {
|
||||
SymbolFlagsMap FlagsFound;
|
||||
|
||||
for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
|
||||
@ -332,6 +333,8 @@ VSO::LookupResult VSO::lookup(AsynchronousSymbolQuery &Query,
|
||||
return {std::move(MaterializationWork), std::move(Names)};
|
||||
}
|
||||
|
||||
ExecutionSession::ExecutionSession(SymbolStringPool &SSP) : SSP(SSP) {}
|
||||
|
||||
VModuleKey ExecutionSession::allocateVModule() { return ++LastKey; }
|
||||
|
||||
void ExecutionSession::releaseVModule(VModuleKey VMod) {
|
||||
|
75
lib/ExecutionEngine/Orc/Legacy.cpp
Normal file
75
lib/ExecutionEngine/Orc/Legacy.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
//===------- 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.
|
@ -52,7 +52,7 @@ ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(
|
||||
/// 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();
|
||||
@ -84,7 +84,7 @@ LegacyJITSymbolResolver::lookup(const SymbolNameSet &Symbols) {
|
||||
/// @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) {
|
||||
|
@ -211,7 +211,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
// 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)) {
|
||||
@ -1000,10 +1000,10 @@ Error RuntimeDyldImpl::resolveExternalSymbols() {
|
||||
// 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();
|
||||
|
@ -731,7 +731,7 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,
|
||||
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: ");
|
||||
@ -750,7 +750,7 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
|
||||
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: ");
|
||||
|
@ -15,6 +15,7 @@ add_llvm_unittest(OrcJITTests
|
||||
IndirectionUtilsTest.cpp
|
||||
GlobalMappingLayerTest.cpp
|
||||
LazyEmittingLayerTest.cpp
|
||||
LegacyAPIInteropTest.cpp
|
||||
ObjectTransformLayerTest.cpp
|
||||
OrcCAPITest.cpp
|
||||
OrcTestCommon.cpp
|
||||
|
90
unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp
Normal file
90
unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
//===----------- 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
|
Loading…
Reference in New Issue
Block a user