Skip to content

Commit 52a34a7

Browse files
committed
[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
1 parent 7694582 commit 52a34a7

File tree

8 files changed

+277
-57
lines changed

8 files changed

+277
-57
lines changed

llvm/include/llvm/ExecutionEngine/Orc/Core.h

+50-30
Original file line numberDiff line numberDiff line change
@@ -411,26 +411,6 @@ reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
411411
Expected<SymbolAliasMap>
412412
buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
413413

414-
/// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
415-
/// re-export a subset of the source JITDylib's symbols in the target.
416-
class ReexportsGenerator {
417-
public:
418-
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
419-
420-
/// Create a reexports generator. If an Allow predicate is passed, only
421-
/// symbols for which the predicate returns true will be reexported. If no
422-
/// Allow predicate is passed, all symbols will be exported.
423-
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
424-
SymbolPredicate Allow = SymbolPredicate());
425-
426-
Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
427-
428-
private:
429-
JITDylib &SourceJD;
430-
bool MatchNonExported = false;
431-
SymbolPredicate Allow;
432-
};
433-
434414
/// Represents the state that a symbol has reached during materialization.
435415
enum class SymbolState : uint8_t {
436416
Invalid, /// No symbol should be in this state.
@@ -502,8 +482,12 @@ class JITDylib {
502482
friend class ExecutionSession;
503483
friend class MaterializationResponsibility;
504484
public:
505-
using GeneratorFunction = std::function<Expected<SymbolNameSet>(
506-
JITDylib &Parent, const SymbolNameSet &Names)>;
485+
class DefinitionGenerator {
486+
public:
487+
virtual ~DefinitionGenerator();
488+
virtual Expected<SymbolNameSet>
489+
tryToGenerate(JITDylib &Parent, const SymbolNameSet &Names) = 0;
490+
};
507491

508492
using AsynchronousSymbolQuerySet =
509493
std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
@@ -519,13 +503,20 @@ class JITDylib {
519503
/// Get a reference to the ExecutionSession for this JITDylib.
520504
ExecutionSession &getExecutionSession() const { return ES; }
521505

522-
/// Set a definition generator. If set, whenever a symbol fails to resolve
523-
/// within this JITDylib, lookup and lookupFlags will pass the unresolved
524-
/// symbols set to the definition generator. The generator can optionally
525-
/// add a definition for the unresolved symbols to the dylib.
526-
void setGenerator(GeneratorFunction DefGenerator) {
527-
this->DefGenerator = std::move(DefGenerator);
528-
}
506+
/// Adds a definition generator to this JITDylib and returns a referenece to
507+
/// it.
508+
///
509+
/// When JITDylibs are searched during lookup, if no existing definition of
510+
/// a symbol is found, then any generators that have been added are run (in
511+
/// the order that they were added) to potentially generate a definition.
512+
template <typename GeneratorT>
513+
GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
514+
515+
/// Remove a definition generator from this JITDylib.
516+
///
517+
/// The given generator must exist in this JITDylib's generators list (i.e.
518+
/// have been added and not yet removed).
519+
void removeGenerator(DefinitionGenerator &G);
529520

530521
/// Set the search order to be used when fixing up definitions in JITDylib.
531522
/// This will replace the previous search order, and apply to any symbol
@@ -744,7 +735,7 @@ class JITDylib {
744735
SymbolTable Symbols;
745736
UnmaterializedInfosMap UnmaterializedInfos;
746737
MaterializingInfosMap MaterializingInfos;
747-
GeneratorFunction DefGenerator;
738+
std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators;
748739
JITDylibSearchList SearchOrder;
749740
};
750741

@@ -932,6 +923,14 @@ class ExecutionSession {
932923
OutstandingMUs;
933924
};
934925

926+
template <typename GeneratorT>
927+
GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
928+
auto &G = *DefGenerator;
929+
ES.runSessionLocked(
930+
[&]() { DefGenerators.push_back(std::move(DefGenerator)); });
931+
return G;
932+
}
933+
935934
template <typename Func>
936935
auto JITDylib::withSearchOrderDo(Func &&F)
937936
-> decltype(F(std::declval<const JITDylibSearchList &>())) {
@@ -971,6 +970,27 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
971970
});
972971
}
973972

973+
/// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
974+
/// re-export a subset of the source JITDylib's symbols in the target.
975+
class ReexportsGenerator : public JITDylib::DefinitionGenerator {
976+
public:
977+
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
978+
979+
/// Create a reexports generator. If an Allow predicate is passed, only
980+
/// symbols for which the predicate returns true will be reexported. If no
981+
/// Allow predicate is passed, all symbols will be exported.
982+
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
983+
SymbolPredicate Allow = SymbolPredicate());
984+
985+
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
986+
const SymbolNameSet &Names) override;
987+
988+
private:
989+
JITDylib &SourceJD;
990+
bool MatchNonExported = false;
991+
SymbolPredicate Allow;
992+
};
993+
974994
/// Mangles symbol names then uniques them in the context of an
975995
/// ExecutionSession.
976996
class MangleAndInterner {

llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h

+42-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ExecutionEngine/Orc/Core.h"
2020
#include "llvm/ExecutionEngine/Orc/OrcError.h"
2121
#include "llvm/ExecutionEngine/RuntimeDyld.h"
22+
#include "llvm/Object/Archive.h"
2223
#include "llvm/Support/DynamicLibrary.h"
2324
#include <algorithm>
2425
#include <cstdint>
@@ -37,6 +38,8 @@ class Value;
3738

3839
namespace orc {
3940

41+
class ObjectLayer;
42+
4043
/// This iterator provides a convenient way to iterate over the elements
4144
/// of an llvm.global_ctors/llvm.global_dtors instance.
4245
///
@@ -237,7 +240,7 @@ class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
237240
/// If an instance of this class is attached to a JITDylib as a fallback
238241
/// definition generator, then any symbol found in the given DynamicLibrary that
239242
/// passes the 'Allow' predicate will be added to the JITDylib.
240-
class DynamicLibrarySearchGenerator {
243+
class DynamicLibrarySearchGenerator : public JITDylib::DefinitionGenerator {
241244
public:
242245
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
243246

@@ -253,26 +256,61 @@ class DynamicLibrarySearchGenerator {
253256
/// Permanently loads the library at the given path and, on success, returns
254257
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
255258
/// in the library. On failure returns the reason the library failed to load.
256-
static Expected<DynamicLibrarySearchGenerator>
259+
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
257260
Load(const char *FileName, char GlobalPrefix,
258261
SymbolPredicate Allow = SymbolPredicate());
259262

260263
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
261264
/// the current process.
262-
static Expected<DynamicLibrarySearchGenerator>
265+
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
263266
GetForCurrentProcess(char GlobalPrefix,
264267
SymbolPredicate Allow = SymbolPredicate()) {
265268
return Load(nullptr, GlobalPrefix, std::move(Allow));
266269
}
267270

268-
Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
271+
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
272+
const SymbolNameSet &Names) override;
269273

270274
private:
271275
sys::DynamicLibrary Dylib;
272276
SymbolPredicate Allow;
273277
char GlobalPrefix;
274278
};
275279

280+
/// A utility class to expose symbols from a static library.
281+
///
282+
/// If an instance of this class is attached to a JITDylib as a fallback
283+
/// definition generator, then any symbol found in the archive will result in
284+
/// the containing object being added to the JITDylib.
285+
class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator {
286+
public:
287+
/// Try to create a StaticLibraryDefinitionGenerator from the given path.
288+
///
289+
/// This call will succeed if the file at the given path is a static library
290+
/// is a valid archive, otherwise it will return an error.
291+
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
292+
Load(ObjectLayer &L, const char *FileName);
293+
294+
/// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
295+
/// Thhis call will succeed if the buffer contains a valid archive, otherwise
296+
/// it will return an error.
297+
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
298+
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
299+
300+
Expected<SymbolNameSet> tryToGenerate(JITDylib &JD,
301+
const SymbolNameSet &Names) override;
302+
303+
private:
304+
StaticLibraryDefinitionGenerator(ObjectLayer &L,
305+
std::unique_ptr<MemoryBuffer> ArchiveBuffer,
306+
Error &Err);
307+
308+
ObjectLayer &L;
309+
std::unique_ptr<MemoryBuffer> ArchiveBuffer;
310+
object::Archive Archive;
311+
size_t UnrealizedObjects = 0;
312+
};
313+
276314
} // end namespace orc
277315
} // end namespace llvm
278316

llvm/lib/ExecutionEngine/Orc/Core.cpp

+51-8
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
694694
Allow(std::move(Allow)) {}
695695

696696
Expected<SymbolNameSet>
697-
ReexportsGenerator::operator()(JITDylib &JD, const SymbolNameSet &Names) {
697+
ReexportsGenerator::tryToGenerate(JITDylib &JD, const SymbolNameSet &Names) {
698698
orc::SymbolNameSet Added;
699699
orc::SymbolAliasMap AliasMap;
700700

@@ -716,6 +716,19 @@ ReexportsGenerator::operator()(JITDylib &JD, const SymbolNameSet &Names) {
716716
return Added;
717717
}
718718

719+
JITDylib::DefinitionGenerator::~DefinitionGenerator() {}
720+
721+
void JITDylib::removeGenerator(DefinitionGenerator &G) {
722+
ES.runSessionLocked([&]() {
723+
auto I = std::find_if(DefGenerators.begin(), DefGenerators.end(),
724+
[&](const std::unique_ptr<DefinitionGenerator> &H) {
725+
return H.get() == &G;
726+
});
727+
assert(I != DefGenerators.end() && "Generator not found");
728+
DefGenerators.erase(I);
729+
});
730+
}
731+
719732
Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
720733
return ES.runSessionLocked([&]() -> Error {
721734
std::vector<SymbolTable::iterator> AddedSyms;
@@ -1159,10 +1172,18 @@ Expected<SymbolFlagsMap> JITDylib::lookupFlags(const SymbolNameSet &Names) {
11591172
if (!Unresolved)
11601173
return Unresolved.takeError();
11611174

1162-
if (DefGenerator && !Unresolved->empty()) {
1163-
auto NewDefs = DefGenerator(*this, *Unresolved);
1175+
/// Run any definition generators.
1176+
for (auto &DG : DefGenerators) {
1177+
1178+
// Bail out early if we've resolved everything.
1179+
if (Unresolved->empty())
1180+
break;
1181+
1182+
// Run this generator.
1183+
auto NewDefs = DG->tryToGenerate(*this, *Unresolved);
11641184
if (!NewDefs)
11651185
return NewDefs.takeError();
1186+
11661187
if (!NewDefs->empty()) {
11671188
auto Unresolved2 = lookupFlagsImpl(Result, *NewDefs);
11681189
if (!Unresolved2)
@@ -1171,7 +1192,10 @@ Expected<SymbolFlagsMap> JITDylib::lookupFlags(const SymbolNameSet &Names) {
11711192
assert(Unresolved2->empty() &&
11721193
"All fallback defs should have been found by lookupFlagsImpl");
11731194
}
1174-
};
1195+
1196+
for (auto &Name : *NewDefs)
1197+
Unresolved->erase(Name);
1198+
}
11751199
return Result;
11761200
});
11771201
}
@@ -1198,13 +1222,25 @@ Error JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
11981222
assert(Q && "Query can not be null");
11991223

12001224
lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs);
1201-
if (DefGenerator && !Unresolved.empty()) {
1202-
auto NewDefs = DefGenerator(*this, Unresolved);
1225+
1226+
// Run any definition generators.
1227+
for (auto &DG : DefGenerators) {
1228+
1229+
// Bail out early if we have resolved everything.
1230+
if (Unresolved.empty())
1231+
break;
1232+
1233+
// Run the generator.
1234+
auto NewDefs = DG->tryToGenerate(*this, Unresolved);
1235+
12031236
if (!NewDefs)
12041237
return NewDefs.takeError();
1238+
1239+
llvm::dbgs() << "NewDefs is " << *NewDefs << "\n";
12051240
if (!NewDefs->empty()) {
12061241
for (auto &D : *NewDefs)
12071242
Unresolved.erase(D);
1243+
llvm::dbgs() << "NewDefs is now " << *NewDefs << "\n";
12081244
lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs);
12091245
assert(NewDefs->empty() &&
12101246
"All fallback defs should have been found by lookupImpl");
@@ -1292,9 +1328,16 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
12921328
SymbolNameSet Unresolved = std::move(Names);
12931329
auto Err = ES.runSessionLocked([&, this]() -> Error {
12941330
QueryComplete = lookupImpl(Q, MUs, Unresolved);
1295-
if (DefGenerator && !Unresolved.empty()) {
1331+
1332+
// Run any definition generators.
1333+
for (auto &DG : DefGenerators) {
1334+
1335+
// Bail out early if we have resolved everything.
1336+
if (Unresolved.empty())
1337+
break;
1338+
12961339
assert(!QueryComplete && "query complete but unresolved symbols remain?");
1297-
auto NewDefs = DefGenerator(*this, Unresolved);
1340+
auto NewDefs = DG->tryToGenerate(*this, Unresolved);
12981341
if (!NewDefs)
12991342
return NewDefs.takeError();
13001343
if (!NewDefs->empty()) {

0 commit comments

Comments
 (0)