mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[ORC] Refactor definition-generation, add a generator for static libraries.
This patch replaces the JITDylib::DefinitionGenerator typedef with a class of the same name, and adds support for attaching a sequence of DefinitionGeneration objects to a JITDylib. This patch also adds a new definition generator, StaticLibraryDefinitionGenerator, that can be used to add symbols fom a static library to a JITDylib. An object from the static library will be added (via a supplied ObjectLayer reference) whenever a symbol from that object is referenced. To enable testing, lli is updated to add support for the --extra-archive option when running in -jit-kind=orc-lazy mode. llvm-svn: 368707
This commit is contained in:
parent
3482b4fef4
commit
44eb111f3c
@ -411,26 +411,6 @@ reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
|
|||||||
Expected<SymbolAliasMap>
|
Expected<SymbolAliasMap>
|
||||||
buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
|
buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
|
||||||
|
|
||||||
/// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
|
|
||||||
/// re-export a subset of the source JITDylib's symbols in the target.
|
|
||||||
class ReexportsGenerator {
|
|
||||||
public:
|
|
||||||
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
|
|
||||||
|
|
||||||
/// Create a reexports generator. If an Allow predicate is passed, only
|
|
||||||
/// symbols for which the predicate returns true will be reexported. If no
|
|
||||||
/// Allow predicate is passed, all symbols will be exported.
|
|
||||||
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
|
|
||||||
SymbolPredicate Allow = SymbolPredicate());
|
|
||||||
|
|
||||||
Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
|
|
||||||
|
|
||||||
private:
|
|
||||||
JITDylib &SourceJD;
|
|
||||||
bool MatchNonExported = false;
|
|
||||||
SymbolPredicate Allow;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Represents the state that a symbol has reached during materialization.
|
/// Represents the state that a symbol has reached during materialization.
|
||||||
enum class SymbolState : uint8_t {
|
enum class SymbolState : uint8_t {
|
||||||
Invalid, /// No symbol should be in this state.
|
Invalid, /// No symbol should be in this state.
|
||||||
@ -502,8 +482,12 @@ class JITDylib {
|
|||||||
friend class ExecutionSession;
|
friend class ExecutionSession;
|
||||||
friend class MaterializationResponsibility;
|
friend class MaterializationResponsibility;
|
||||||
public:
|
public:
|
||||||
using GeneratorFunction = std::function<Expected<SymbolNameSet>(
|
class DefinitionGenerator {
|
||||||
JITDylib &Parent, const SymbolNameSet &Names)>;
|
public:
|
||||||
|
virtual ~DefinitionGenerator();
|
||||||
|
virtual Expected<SymbolNameSet>
|
||||||
|
tryToGenerate(JITDylib &Parent, const SymbolNameSet &Names) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
using AsynchronousSymbolQuerySet =
|
using AsynchronousSymbolQuerySet =
|
||||||
std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
|
std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
|
||||||
@ -519,13 +503,20 @@ public:
|
|||||||
/// Get a reference to the ExecutionSession for this JITDylib.
|
/// Get a reference to the ExecutionSession for this JITDylib.
|
||||||
ExecutionSession &getExecutionSession() const { return ES; }
|
ExecutionSession &getExecutionSession() const { return ES; }
|
||||||
|
|
||||||
/// Set a definition generator. If set, whenever a symbol fails to resolve
|
/// Adds a definition generator to this JITDylib and returns a referenece to
|
||||||
/// within this JITDylib, lookup and lookupFlags will pass the unresolved
|
/// it.
|
||||||
/// symbols set to the definition generator. The generator can optionally
|
///
|
||||||
/// add a definition for the unresolved symbols to the dylib.
|
/// When JITDylibs are searched during lookup, if no existing definition of
|
||||||
void setGenerator(GeneratorFunction DefGenerator) {
|
/// a symbol is found, then any generators that have been added are run (in
|
||||||
this->DefGenerator = std::move(DefGenerator);
|
/// the order that they were added) to potentially generate a definition.
|
||||||
}
|
template <typename GeneratorT>
|
||||||
|
GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
|
||||||
|
|
||||||
|
/// Remove a definition generator from this JITDylib.
|
||||||
|
///
|
||||||
|
/// The given generator must exist in this JITDylib's generators list (i.e.
|
||||||
|
/// have been added and not yet removed).
|
||||||
|
void removeGenerator(DefinitionGenerator &G);
|
||||||
|
|
||||||
/// Set the search order to be used when fixing up definitions in JITDylib.
|
/// Set the search order to be used when fixing up definitions in JITDylib.
|
||||||
/// This will replace the previous search order, and apply to any symbol
|
/// This will replace the previous search order, and apply to any symbol
|
||||||
@ -744,7 +735,7 @@ private:
|
|||||||
SymbolTable Symbols;
|
SymbolTable Symbols;
|
||||||
UnmaterializedInfosMap UnmaterializedInfos;
|
UnmaterializedInfosMap UnmaterializedInfos;
|
||||||
MaterializingInfosMap MaterializingInfos;
|
MaterializingInfosMap MaterializingInfos;
|
||||||
GeneratorFunction DefGenerator;
|
std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators;
|
||||||
JITDylibSearchList SearchOrder;
|
JITDylibSearchList SearchOrder;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -932,6 +923,14 @@ private:
|
|||||||
OutstandingMUs;
|
OutstandingMUs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename GeneratorT>
|
||||||
|
GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
|
||||||
|
auto &G = *DefGenerator;
|
||||||
|
ES.runSessionLocked(
|
||||||
|
[&]() { DefGenerators.push_back(std::move(DefGenerator)); });
|
||||||
|
return G;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
auto JITDylib::withSearchOrderDo(Func &&F)
|
auto JITDylib::withSearchOrderDo(Func &&F)
|
||||||
-> decltype(F(std::declval<const JITDylibSearchList &>())) {
|
-> decltype(F(std::declval<const JITDylibSearchList &>())) {
|
||||||
@ -971,6 +970,27 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
|
||||||
|
/// re-export a subset of the source JITDylib's symbols in the target.
|
||||||
|
class ReexportsGenerator : public JITDylib::DefinitionGenerator {
|
||||||
|
public:
|
||||||
|
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
|
||||||
|
|
||||||
|
/// Create a reexports generator. If an Allow predicate is passed, only
|
||||||
|
/// symbols for which the predicate returns true will be reexported. If no
|
||||||
|
/// Allow predicate is passed, all symbols will be exported.
|
||||||
|
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
|
||||||
|
SymbolPredicate Allow = SymbolPredicate());
|
||||||
|
|
||||||
|
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
|
||||||
|
const SymbolNameSet &Names) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JITDylib &SourceJD;
|
||||||
|
bool MatchNonExported = false;
|
||||||
|
SymbolPredicate Allow;
|
||||||
|
};
|
||||||
|
|
||||||
/// Mangles symbol names then uniques them in the context of an
|
/// Mangles symbol names then uniques them in the context of an
|
||||||
/// ExecutionSession.
|
/// ExecutionSession.
|
||||||
class MangleAndInterner {
|
class MangleAndInterner {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "llvm/ExecutionEngine/Orc/Core.h"
|
#include "llvm/ExecutionEngine/Orc/Core.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/OrcError.h"
|
#include "llvm/ExecutionEngine/Orc/OrcError.h"
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
|
#include "llvm/Object/Archive.h"
|
||||||
#include "llvm/Support/DynamicLibrary.h"
|
#include "llvm/Support/DynamicLibrary.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -37,6 +38,8 @@ class Value;
|
|||||||
|
|
||||||
namespace orc {
|
namespace orc {
|
||||||
|
|
||||||
|
class ObjectLayer;
|
||||||
|
|
||||||
/// This iterator provides a convenient way to iterate over the elements
|
/// This iterator provides a convenient way to iterate over the elements
|
||||||
/// of an llvm.global_ctors/llvm.global_dtors instance.
|
/// of an llvm.global_ctors/llvm.global_dtors instance.
|
||||||
///
|
///
|
||||||
@ -237,7 +240,7 @@ public:
|
|||||||
/// If an instance of this class is attached to a JITDylib as a fallback
|
/// If an instance of this class is attached to a JITDylib as a fallback
|
||||||
/// definition generator, then any symbol found in the given DynamicLibrary that
|
/// definition generator, then any symbol found in the given DynamicLibrary that
|
||||||
/// passes the 'Allow' predicate will be added to the JITDylib.
|
/// passes the 'Allow' predicate will be added to the JITDylib.
|
||||||
class DynamicLibrarySearchGenerator {
|
class DynamicLibrarySearchGenerator : public JITDylib::DefinitionGenerator {
|
||||||
public:
|
public:
|
||||||
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
|
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
|
||||||
|
|
||||||
@ -253,19 +256,20 @@ public:
|
|||||||
/// Permanently loads the library at the given path and, on success, returns
|
/// Permanently loads the library at the given path and, on success, returns
|
||||||
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
|
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
|
||||||
/// in the library. On failure returns the reason the library failed to load.
|
/// in the library. On failure returns the reason the library failed to load.
|
||||||
static Expected<DynamicLibrarySearchGenerator>
|
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
|
||||||
Load(const char *FileName, char GlobalPrefix,
|
Load(const char *FileName, char GlobalPrefix,
|
||||||
SymbolPredicate Allow = SymbolPredicate());
|
SymbolPredicate Allow = SymbolPredicate());
|
||||||
|
|
||||||
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
|
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
|
||||||
/// the current process.
|
/// the current process.
|
||||||
static Expected<DynamicLibrarySearchGenerator>
|
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
|
||||||
GetForCurrentProcess(char GlobalPrefix,
|
GetForCurrentProcess(char GlobalPrefix,
|
||||||
SymbolPredicate Allow = SymbolPredicate()) {
|
SymbolPredicate Allow = SymbolPredicate()) {
|
||||||
return Load(nullptr, GlobalPrefix, std::move(Allow));
|
return Load(nullptr, GlobalPrefix, std::move(Allow));
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
|
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
|
||||||
|
const SymbolNameSet &Names) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sys::DynamicLibrary Dylib;
|
sys::DynamicLibrary Dylib;
|
||||||
@ -273,6 +277,40 @@ private:
|
|||||||
char GlobalPrefix;
|
char GlobalPrefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A utility class to expose symbols from a static library.
|
||||||
|
///
|
||||||
|
/// If an instance of this class is attached to a JITDylib as a fallback
|
||||||
|
/// definition generator, then any symbol found in the archive will result in
|
||||||
|
/// the containing object being added to the JITDylib.
|
||||||
|
class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator {
|
||||||
|
public:
|
||||||
|
/// Try to create a StaticLibraryDefinitionGenerator from the given path.
|
||||||
|
///
|
||||||
|
/// This call will succeed if the file at the given path is a static library
|
||||||
|
/// is a valid archive, otherwise it will return an error.
|
||||||
|
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
|
||||||
|
Load(ObjectLayer &L, const char *FileName);
|
||||||
|
|
||||||
|
/// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
|
||||||
|
/// Thhis call will succeed if the buffer contains a valid archive, otherwise
|
||||||
|
/// it will return an error.
|
||||||
|
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
|
||||||
|
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
|
||||||
|
|
||||||
|
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
|
||||||
|
const SymbolNameSet &Names) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
StaticLibraryDefinitionGenerator(ObjectLayer &L,
|
||||||
|
std::unique_ptr<MemoryBuffer> ArchiveBuffer,
|
||||||
|
Error &Err);
|
||||||
|
|
||||||
|
ObjectLayer &L;
|
||||||
|
std::unique_ptr<MemoryBuffer> ArchiveBuffer;
|
||||||
|
object::Archive Archive;
|
||||||
|
size_t UnrealizedObjects = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace orc
|
} // end namespace orc
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
@ -694,7 +694,7 @@ ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
|
|||||||
Allow(std::move(Allow)) {}
|
Allow(std::move(Allow)) {}
|
||||||
|
|
||||||
Expected<SymbolNameSet>
|
Expected<SymbolNameSet>
|
||||||
ReexportsGenerator::operator()(JITDylib &JD, const SymbolNameSet &Names) {
|
ReexportsGenerator::tryToGenerate(JITDylib &JD, const SymbolNameSet &Names) {
|
||||||
orc::SymbolNameSet Added;
|
orc::SymbolNameSet Added;
|
||||||
orc::SymbolAliasMap AliasMap;
|
orc::SymbolAliasMap AliasMap;
|
||||||
|
|
||||||
@ -716,6 +716,19 @@ ReexportsGenerator::operator()(JITDylib &JD, const SymbolNameSet &Names) {
|
|||||||
return Added;
|
return Added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JITDylib::DefinitionGenerator::~DefinitionGenerator() {}
|
||||||
|
|
||||||
|
void JITDylib::removeGenerator(DefinitionGenerator &G) {
|
||||||
|
ES.runSessionLocked([&]() {
|
||||||
|
auto I = std::find_if(DefGenerators.begin(), DefGenerators.end(),
|
||||||
|
[&](const std::unique_ptr<DefinitionGenerator> &H) {
|
||||||
|
return H.get() == &G;
|
||||||
|
});
|
||||||
|
assert(I != DefGenerators.end() && "Generator not found");
|
||||||
|
DefGenerators.erase(I);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
|
Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
|
||||||
return ES.runSessionLocked([&]() -> Error {
|
return ES.runSessionLocked([&]() -> Error {
|
||||||
std::vector<SymbolTable::iterator> AddedSyms;
|
std::vector<SymbolTable::iterator> AddedSyms;
|
||||||
@ -1159,10 +1172,18 @@ Expected<SymbolFlagsMap> JITDylib::lookupFlags(const SymbolNameSet &Names) {
|
|||||||
if (!Unresolved)
|
if (!Unresolved)
|
||||||
return Unresolved.takeError();
|
return Unresolved.takeError();
|
||||||
|
|
||||||
if (DefGenerator && !Unresolved->empty()) {
|
/// Run any definition generators.
|
||||||
auto NewDefs = DefGenerator(*this, *Unresolved);
|
for (auto &DG : DefGenerators) {
|
||||||
|
|
||||||
|
// Bail out early if we've resolved everything.
|
||||||
|
if (Unresolved->empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Run this generator.
|
||||||
|
auto NewDefs = DG->tryToGenerate(*this, *Unresolved);
|
||||||
if (!NewDefs)
|
if (!NewDefs)
|
||||||
return NewDefs.takeError();
|
return NewDefs.takeError();
|
||||||
|
|
||||||
if (!NewDefs->empty()) {
|
if (!NewDefs->empty()) {
|
||||||
auto Unresolved2 = lookupFlagsImpl(Result, *NewDefs);
|
auto Unresolved2 = lookupFlagsImpl(Result, *NewDefs);
|
||||||
if (!Unresolved2)
|
if (!Unresolved2)
|
||||||
@ -1171,7 +1192,10 @@ Expected<SymbolFlagsMap> JITDylib::lookupFlags(const SymbolNameSet &Names) {
|
|||||||
assert(Unresolved2->empty() &&
|
assert(Unresolved2->empty() &&
|
||||||
"All fallback defs should have been found by lookupFlagsImpl");
|
"All fallback defs should have been found by lookupFlagsImpl");
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
for (auto &Name : *NewDefs)
|
||||||
|
Unresolved->erase(Name);
|
||||||
|
}
|
||||||
return Result;
|
return Result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1198,13 +1222,25 @@ Error JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
|||||||
assert(Q && "Query can not be null");
|
assert(Q && "Query can not be null");
|
||||||
|
|
||||||
lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs);
|
lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs);
|
||||||
if (DefGenerator && !Unresolved.empty()) {
|
|
||||||
auto NewDefs = DefGenerator(*this, Unresolved);
|
// Run any definition generators.
|
||||||
|
for (auto &DG : DefGenerators) {
|
||||||
|
|
||||||
|
// Bail out early if we have resolved everything.
|
||||||
|
if (Unresolved.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Run the generator.
|
||||||
|
auto NewDefs = DG->tryToGenerate(*this, Unresolved);
|
||||||
|
|
||||||
if (!NewDefs)
|
if (!NewDefs)
|
||||||
return NewDefs.takeError();
|
return NewDefs.takeError();
|
||||||
|
|
||||||
|
llvm::dbgs() << "NewDefs is " << *NewDefs << "\n";
|
||||||
if (!NewDefs->empty()) {
|
if (!NewDefs->empty()) {
|
||||||
for (auto &D : *NewDefs)
|
for (auto &D : *NewDefs)
|
||||||
Unresolved.erase(D);
|
Unresolved.erase(D);
|
||||||
|
llvm::dbgs() << "NewDefs is now " << *NewDefs << "\n";
|
||||||
lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs);
|
lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs);
|
||||||
assert(NewDefs->empty() &&
|
assert(NewDefs->empty() &&
|
||||||
"All fallback defs should have been found by lookupImpl");
|
"All fallback defs should have been found by lookupImpl");
|
||||||
@ -1292,9 +1328,16 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
|
|||||||
SymbolNameSet Unresolved = std::move(Names);
|
SymbolNameSet Unresolved = std::move(Names);
|
||||||
auto Err = ES.runSessionLocked([&, this]() -> Error {
|
auto Err = ES.runSessionLocked([&, this]() -> Error {
|
||||||
QueryComplete = lookupImpl(Q, MUs, Unresolved);
|
QueryComplete = lookupImpl(Q, MUs, Unresolved);
|
||||||
if (DefGenerator && !Unresolved.empty()) {
|
|
||||||
|
// Run any definition generators.
|
||||||
|
for (auto &DG : DefGenerators) {
|
||||||
|
|
||||||
|
// Bail out early if we have resolved everything.
|
||||||
|
if (Unresolved.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
assert(!QueryComplete && "query complete but unresolved symbols remain?");
|
assert(!QueryComplete && "query complete but unresolved symbols remain?");
|
||||||
auto NewDefs = DefGenerator(*this, Unresolved);
|
auto NewDefs = DG->tryToGenerate(*this, Unresolved);
|
||||||
if (!NewDefs)
|
if (!NewDefs)
|
||||||
return NewDefs.takeError();
|
return NewDefs.takeError();
|
||||||
if (!NewDefs->empty()) {
|
if (!NewDefs->empty()) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
||||||
|
|
||||||
|
#include "llvm/ExecutionEngine/Orc/Layer.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/GlobalVariable.h"
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
@ -178,20 +179,20 @@ DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
|
|||||||
: Dylib(std::move(Dylib)), Allow(std::move(Allow)),
|
: Dylib(std::move(Dylib)), Allow(std::move(Allow)),
|
||||||
GlobalPrefix(GlobalPrefix) {}
|
GlobalPrefix(GlobalPrefix) {}
|
||||||
|
|
||||||
Expected<DynamicLibrarySearchGenerator>
|
Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
|
||||||
DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
|
DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
|
||||||
SymbolPredicate Allow) {
|
SymbolPredicate Allow) {
|
||||||
std::string ErrMsg;
|
std::string ErrMsg;
|
||||||
auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
|
auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
|
||||||
if (!Lib.isValid())
|
if (!Lib.isValid())
|
||||||
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
|
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
|
||||||
return DynamicLibrarySearchGenerator(std::move(Lib), GlobalPrefix,
|
return llvm::make_unique<DynamicLibrarySearchGenerator>(
|
||||||
std::move(Allow));
|
std::move(Lib), GlobalPrefix, std::move(Allow));
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<SymbolNameSet>
|
Expected<SymbolNameSet>
|
||||||
DynamicLibrarySearchGenerator::operator()(JITDylib &JD,
|
DynamicLibrarySearchGenerator::tryToGenerate(JITDylib &JD,
|
||||||
const SymbolNameSet &Names) {
|
const SymbolNameSet &Names) {
|
||||||
orc::SymbolNameSet Added;
|
orc::SymbolNameSet Added;
|
||||||
orc::SymbolMap NewSymbols;
|
orc::SymbolMap NewSymbols;
|
||||||
|
|
||||||
@ -226,5 +227,82 @@ DynamicLibrarySearchGenerator::operator()(JITDylib &JD,
|
|||||||
return Added;
|
return Added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
|
||||||
|
StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
|
||||||
|
auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName));
|
||||||
|
|
||||||
|
if (!ArchiveBuffer)
|
||||||
|
return ArchiveBuffer.takeError();
|
||||||
|
|
||||||
|
return Create(L, std::move(*ArchiveBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
|
||||||
|
StaticLibraryDefinitionGenerator::Create(
|
||||||
|
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
|
||||||
|
Error Err = Error::success();
|
||||||
|
|
||||||
|
std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
|
||||||
|
new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err));
|
||||||
|
|
||||||
|
if (Err)
|
||||||
|
return std::move(Err);
|
||||||
|
|
||||||
|
return std::move(ADG);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expected<SymbolNameSet>
|
||||||
|
StaticLibraryDefinitionGenerator::tryToGenerate(JITDylib &JD,
|
||||||
|
const SymbolNameSet &Names) {
|
||||||
|
|
||||||
|
DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
|
||||||
|
SymbolNameSet NewDefs;
|
||||||
|
|
||||||
|
for (const auto &Name : Names) {
|
||||||
|
auto Child = Archive.findSym(*Name);
|
||||||
|
if (!Child)
|
||||||
|
return Child.takeError();
|
||||||
|
if (*Child == None)
|
||||||
|
continue;
|
||||||
|
auto ChildBuffer = (*Child)->getMemoryBufferRef();
|
||||||
|
if (!ChildBuffer)
|
||||||
|
return ChildBuffer.takeError();
|
||||||
|
ChildBufferInfos.insert(
|
||||||
|
{ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
|
||||||
|
NewDefs.insert(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto ChildBufferInfo : ChildBufferInfos) {
|
||||||
|
MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
|
||||||
|
ChildBufferInfo.second);
|
||||||
|
|
||||||
|
if (auto Err =
|
||||||
|
L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef), VModuleKey()))
|
||||||
|
return std::move(Err);
|
||||||
|
|
||||||
|
--UnrealizedObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
|
||||||
|
ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err)
|
||||||
|
: L(L), ArchiveBuffer(std::move(ArchiveBuffer)),
|
||||||
|
Archive(*this->ArchiveBuffer, Err) {
|
||||||
|
|
||||||
|
if (Err)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Error Err2 = Error::success();
|
||||||
|
for (auto _ : Archive.children(Err2)) {
|
||||||
|
(void)_;
|
||||||
|
++UnrealizedObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to check this: We will leave it to the caller.
|
||||||
|
Err = std::move(Err2);
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace orc.
|
} // End namespace orc.
|
||||||
} // End namespace llvm.
|
} // End namespace llvm.
|
||||||
|
11
test/ExecutionEngine/OrcLazy/static-library-support.ll
Normal file
11
test/ExecutionEngine/OrcLazy/static-library-support.ll
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
; This first line will generate the .o files for the next run line
|
||||||
|
; RUN: llc -filetype=obj -o %t.o %p/Inputs/basic-object-source.ll
|
||||||
|
; RUN: llvm-ar r %t.a %t.o
|
||||||
|
; RUN: lli -jit-kind=orc-lazy -extra-archive %t.a %s
|
||||||
|
|
||||||
|
declare i32 @foo()
|
||||||
|
|
||||||
|
define i32 @main() {
|
||||||
|
%r = call i32 @foo( ) ; <i32> [#uses=1]
|
||||||
|
ret i32 %r
|
||||||
|
}
|
@ -792,7 +792,7 @@ int runOrcLazyJIT(const char *ProgName) {
|
|||||||
});
|
});
|
||||||
return TSM;
|
return TSM;
|
||||||
});
|
});
|
||||||
J->getMainJITDylib().setGenerator(
|
J->getMainJITDylib().addGenerator(
|
||||||
ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
|
ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
|
||||||
J->getDataLayout().getGlobalPrefix())));
|
J->getDataLayout().getGlobalPrefix())));
|
||||||
|
|
||||||
@ -832,6 +832,16 @@ int runOrcLazyJIT(const char *ProgName) {
|
|||||||
ExitOnErr(
|
ExitOnErr(
|
||||||
J->addLazyIRModule(JD, orc::ThreadSafeModule(std::move(M), TSCtx)));
|
J->addLazyIRModule(JD, orc::ThreadSafeModule(std::move(M), TSCtx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto EAItr = ExtraArchives.begin(), EAEnd = ExtraArchives.end();
|
||||||
|
EAItr != EAEnd; ++EAItr) {
|
||||||
|
auto EAIdx = ExtraArchives.getPosition(EAItr - ExtraArchives.begin());
|
||||||
|
assert(EAIdx != 0 && "ExtraArchive should have index > 0");
|
||||||
|
auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));
|
||||||
|
auto &JD = *JDItr->second;
|
||||||
|
JD.addGenerator(ExitOnErr(orc::StaticLibraryDefinitionGenerator::Load(
|
||||||
|
J->getObjLinkingLayer(), EAItr->c_str())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the objects.
|
// Add the objects.
|
||||||
|
@ -380,7 +380,7 @@ Error loadProcessSymbols(Session &S) {
|
|||||||
auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr Name) {
|
auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr Name) {
|
||||||
return Name != InternedEntryPointName;
|
return Name != InternedEntryPointName;
|
||||||
};
|
};
|
||||||
S.ES.getMainJITDylib().setGenerator(
|
S.ES.getMainJITDylib().addGenerator(
|
||||||
ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
|
ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
|
||||||
GlobalPrefix, FilterMainEntryPoint)));
|
GlobalPrefix, FilterMainEntryPoint)));
|
||||||
|
|
||||||
|
@ -243,14 +243,15 @@ TEST_F(CoreAPIsStandardTest, LookupFlagsTest) {
|
|||||||
|
|
||||||
TEST_F(CoreAPIsStandardTest, LookupWithGeneratorFailure) {
|
TEST_F(CoreAPIsStandardTest, LookupWithGeneratorFailure) {
|
||||||
|
|
||||||
class BadGenerator {
|
class BadGenerator : public JITDylib::DefinitionGenerator {
|
||||||
public:
|
public:
|
||||||
Expected<SymbolNameSet> operator()(JITDylib &, const SymbolNameSet &) {
|
Expected<SymbolNameSet> tryToGenerate(JITDylib &,
|
||||||
|
const SymbolNameSet &) override {
|
||||||
return make_error<StringError>("BadGenerator", inconvertibleErrorCode());
|
return make_error<StringError>("BadGenerator", inconvertibleErrorCode());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JD.setGenerator(BadGenerator());
|
JD.addGenerator(llvm::make_unique<BadGenerator>());
|
||||||
|
|
||||||
EXPECT_THAT_ERROR(JD.lookupFlags({Foo}).takeError(), Failed<StringError>())
|
EXPECT_THAT_ERROR(JD.lookupFlags({Foo}).takeError(), Failed<StringError>())
|
||||||
<< "Generator failure did not propagate through lookupFlags";
|
<< "Generator failure did not propagate through lookupFlags";
|
||||||
@ -343,7 +344,7 @@ TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) {
|
|||||||
|
|
||||||
auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; };
|
auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; };
|
||||||
|
|
||||||
JD.setGenerator(ReexportsGenerator(JD2, false, Filter));
|
JD.addGenerator(llvm::make_unique<ReexportsGenerator>(JD2, false, Filter));
|
||||||
|
|
||||||
auto Flags = cantFail(JD.lookupFlags({Foo, Bar, Baz}));
|
auto Flags = cantFail(JD.lookupFlags({Foo, Bar, Baz}));
|
||||||
EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results";
|
EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results";
|
||||||
@ -667,10 +668,29 @@ TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) {
|
|||||||
TEST_F(CoreAPIsStandardTest, GeneratorTest) {
|
TEST_F(CoreAPIsStandardTest, GeneratorTest) {
|
||||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
|
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
|
||||||
|
|
||||||
JD.setGenerator([&](JITDylib &JD2, const SymbolNameSet &Names) {
|
class TestGenerator : public JITDylib::DefinitionGenerator {
|
||||||
cantFail(JD2.define(absoluteSymbols({{Bar, BarSym}})));
|
public:
|
||||||
return SymbolNameSet({Bar});
|
TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {}
|
||||||
});
|
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
|
||||||
|
const SymbolNameSet &Names) {
|
||||||
|
SymbolMap NewDefs;
|
||||||
|
SymbolNameSet NewNames;
|
||||||
|
|
||||||
|
for (auto &Name : Names) {
|
||||||
|
if (Symbols.count(Name)) {
|
||||||
|
NewDefs[Name] = Symbols[Name];
|
||||||
|
NewNames.insert(Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cantFail(JD.define(absoluteSymbols(std::move(NewDefs))));
|
||||||
|
return NewNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
SymbolMap Symbols;
|
||||||
|
};
|
||||||
|
|
||||||
|
JD.addGenerator(llvm::make_unique<TestGenerator>(SymbolMap({{Bar, BarSym}})));
|
||||||
|
|
||||||
auto Result =
|
auto Result =
|
||||||
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar}));
|
cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar}));
|
||||||
|
Loading…
Reference in New Issue
Block a user