Update clang to r339409b.
Change-Id: Ied8a188bb072c40035320acedc86164b66d920af
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index 8bd21a0..2003f8e 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -16,6 +16,7 @@
#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -23,6 +24,7 @@
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
@@ -61,41 +63,73 @@
class ExtractingIRMaterializationUnit;
class CompileOnDemandLayer2 : public IRLayer {
- friend class ExtractingIRMaterializationUnit;
+ friend class PartitioningIRMaterializationUnit;
public:
/// Builder for IndirectStubsManagers.
using IndirectStubsManagerBuilder =
std::function<std::unique_ptr<IndirectStubsManager>()>;
- using GetAvailableContextFunction = std::function<LLVMContext &()>;
+ using GlobalValueSet = std::set<const GlobalValue *>;
+ /// Partitioning function.
+ using PartitionFunction =
+ std::function<Optional<GlobalValueSet>(GlobalValueSet Requested)>;
+
+ /// Off-the-shelf partitioning which compiles all requested symbols (usually
+ /// a single function at a time).
+ static Optional<GlobalValueSet> compileRequested(GlobalValueSet Requested);
+
+ /// Off-the-shelf partitioning which compiles whole modules whenever any
+ /// symbol in them is requested.
+ static Optional<GlobalValueSet> compileWholeModule(GlobalValueSet Requested);
+
+ /// Construct a CompileOnDemandLayer2.
CompileOnDemandLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
- JITCompileCallbackManager &CCMgr,
- IndirectStubsManagerBuilder BuildIndirectStubsManager,
- GetAvailableContextFunction GetAvailableContext);
+ LazyCallThroughManager &LCTMgr,
+ IndirectStubsManagerBuilder BuildIndirectStubsManager);
- Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) override;
+ /// Sets the partition function.
+ void setPartitionFunction(PartitionFunction Partition);
+ /// Emits the given module. This should not be called by clients: it will be
+ /// called by the JIT when a definition added via the add method is requested.
void emit(MaterializationResponsibility R, VModuleKey K,
- std::unique_ptr<Module> M) override;
+ ThreadSafeModule TSM) override;
private:
- using StubManagersMap =
- std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>;
+ struct PerDylibResources {
+ public:
+ PerDylibResources(JITDylib &ImplD,
+ std::unique_ptr<IndirectStubsManager> ISMgr)
+ : ImplD(ImplD), ISMgr(std::move(ISMgr)) {}
+ JITDylib &getImplDylib() { return ImplD; }
+ IndirectStubsManager &getISManager() { return *ISMgr; }
- IndirectStubsManager &getStubsManager(const VSO &V);
+ private:
+ JITDylib &ImplD;
+ std::unique_ptr<IndirectStubsManager> ISMgr;
+ };
- void emitExtractedFunctionsModule(MaterializationResponsibility R,
- std::unique_ptr<Module> M);
+ using PerDylibResourcesMap = std::map<const JITDylib *, PerDylibResources>;
+
+ PerDylibResources &getPerDylibResources(JITDylib &TargetD);
+
+ void cleanUpModule(Module &M);
+
+ void expandPartition(GlobalValueSet &Partition);
+
+ void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM,
+ IRMaterializationUnit::SymbolNameToDefinitionMap Defs);
mutable std::mutex CODLayerMutex;
IRLayer &BaseLayer;
- JITCompileCallbackManager &CCMgr;
+ LazyCallThroughManager &LCTMgr;
IndirectStubsManagerBuilder BuildIndirectStubsManager;
- StubManagersMap StubsMgrs;
- GetAvailableContextFunction GetAvailableContext;
+ PerDylibResourcesMap DylibResources;
+ PartitionFunction Partition = compileRequested;
+ SymbolLinkagePromoter PromoteSymbols;
};
/// Compile-on-demand layer.
@@ -158,25 +192,6 @@
return llvm::make_unique<RO>(std::move(ResourcePtr));
}
- class StaticGlobalRenamer {
- public:
- StaticGlobalRenamer() = default;
- StaticGlobalRenamer(StaticGlobalRenamer &&) = default;
- StaticGlobalRenamer &operator=(StaticGlobalRenamer &&) = default;
-
- void rename(Module &M) {
- for (auto &F : M)
- if (F.hasLocalLinkage())
- F.setName("$static." + Twine(NextId++));
- for (auto &G : M.globals())
- if (G.hasLocalLinkage())
- G.setName("$static." + Twine(NextId++));
- }
-
- private:
- unsigned NextId = 0;
- };
-
struct LogicalDylib {
struct SourceModuleEntry {
std::unique_ptr<Module> SourceMod;
@@ -230,7 +245,7 @@
VModuleKey K;
std::shared_ptr<SymbolResolver> BackingResolver;
std::unique_ptr<IndirectStubsMgrT> StubsMgr;
- StaticGlobalRenamer StaticRenamer;
+ SymbolLinkagePromoter PromoteSymbols;
SourceModulesList SourceModules;
std::vector<VModuleKey> BaseLayerVModuleKeys;
};
@@ -352,14 +367,9 @@
private:
Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
- // Rename all static functions / globals to $static.X :
- // This will unique the names across all modules in the logical dylib,
- // simplifying symbol lookup.
- LD.StaticRenamer.rename(*SrcMPtr);
-
- // Bump the linkage and rename any anonymous/private members in SrcM to
- // ensure that everything will resolve properly after we partition SrcM.
- makeAllSymbolsExternallyAccessible(*SrcMPtr);
+ // Rename anonymous globals and promote linkage to ensure that everything
+ // will resolve properly after we partition SrcM.
+ LD.PromoteSymbols(*SrcMPtr);
// Create a logical module handle for SrcM within the logical dylib.
Module &SrcM = *SrcMPtr;
@@ -500,28 +510,29 @@
auto GVsResolver = createSymbolResolver(
[&LD, LegacyLookup](const SymbolNameSet &Symbols) {
- auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
+ auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
- if (!SymbolFlags) {
- logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
- "CODLayer/GVsResolver flags lookup failed: ");
- return SymbolFlagsMap();
+ if (!RS) {
+ logAllUnhandledErrors(
+ RS.takeError(), errs(),
+ "CODLayer/GVsResolver responsibility set lookup failed: ");
+ return SymbolNameSet();
}
- if (SymbolFlags->size() == Symbols.size())
- return *SymbolFlags;
+ if (RS->size() == Symbols.size())
+ return *RS;
SymbolNameSet NotFoundViaLegacyLookup;
for (auto &S : Symbols)
- if (!SymbolFlags->count(S))
+ if (!RS->count(S))
NotFoundViaLegacyLookup.insert(S);
- auto SymbolFlags2 =
- LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+ auto RS2 =
+ LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
- for (auto &KV : SymbolFlags2)
- (*SymbolFlags)[KV.first] = std::move(KV.second);
+ for (auto &S : RS2)
+ (*RS).insert(S);
- return *SymbolFlags;
+ return *RS;
},
[this, &LD,
LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
@@ -669,28 +680,29 @@
// Create memory manager and symbol resolver.
auto Resolver = createSymbolResolver(
[&LD, LegacyLookup](const SymbolNameSet &Symbols) {
- auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
- if (!SymbolFlags) {
- logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
- "CODLayer/SubResolver flags lookup failed: ");
- return SymbolFlagsMap();
+ auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
+ if (!RS) {
+ logAllUnhandledErrors(
+ RS.takeError(), errs(),
+ "CODLayer/SubResolver responsibility set lookup failed: ");
+ return SymbolNameSet();
}
- if (SymbolFlags->size() == Symbols.size())
- return *SymbolFlags;
+ if (RS->size() == Symbols.size())
+ return *RS;
SymbolNameSet NotFoundViaLegacyLookup;
for (auto &S : Symbols)
- if (!SymbolFlags->count(S))
+ if (!RS->count(S))
NotFoundViaLegacyLookup.insert(S);
- auto SymbolFlags2 =
- LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+ auto RS2 =
+ LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
- for (auto &KV : SymbolFlags2)
- (*SymbolFlags)[KV.first] = std::move(KV.second);
+ for (auto &S : RS2)
+ (*RS).insert(S);
- return *SymbolFlags;
+ return *RS;
},
[this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
SymbolNameSet Symbols) {
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index 213a591..3d02f9d 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -16,7 +16,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
index 8456dff..f3ea2ae 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
@@ -18,6 +18,7 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
#include <list>
#include <map>
@@ -25,6 +26,8 @@
#include <set>
#include <vector>
+#define DEBUG_TYPE "orc"
+
namespace llvm {
namespace orc {
@@ -33,7 +36,7 @@
class ExecutionSession;
class MaterializationUnit;
class MaterializationResponsibility;
-class VSO;
+class JITDylib;
/// VModuleKey provides a unique identifier (allocated and managed by
/// ExecutionSessions) for a module added to the JIT.
@@ -43,34 +46,50 @@
// efficiency).
using SymbolNameSet = std::set<SymbolStringPtr>;
-/// Render a SymbolNameSet to an ostream.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
-
/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
/// (address/flags pairs).
using SymbolMap = std::map<SymbolStringPtr, JITEvaluatedSymbol>;
-/// Render a SymbolMap to an ostream.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
-
/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>;
-/// Render a SymbolMap to an ostream.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &Symbols);
-
/// A base class for materialization failures that allows the failing
/// symbols to be obtained for logging.
-using SymbolDependenceMap = std::map<VSO *, SymbolNameSet>;
+using SymbolDependenceMap = std::map<JITDylib *, SymbolNameSet>;
+
+/// A list of JITDylib pointers.
+using JITDylibList = std::vector<JITDylib *>;
+
+/// Render a SymbolStringPtr.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
+
+/// Render a SymbolNameSet.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
+
+/// Render a SymbolFlagsMap entry.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV);
+
+/// Render a SymbolMap entry.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV);
+
+/// Render a SymbolFlagsMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
+
+/// Render a SymbolMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
+
+/// Render a SymbolDependenceMap entry.
+raw_ostream &operator<<(raw_ostream &OS,
+ const SymbolDependenceMap::value_type &KV);
/// Render a SymbolDependendeMap.
raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
-/// A list of VSO pointers.
-using VSOList = std::vector<VSO *>;
+/// Render a MaterializationUnit.
+raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
-/// Render a VSOList.
-raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs);
+/// Render a JITDylibList.
+raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs);
/// Callback to notify client that symbols have been resolved.
using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
@@ -86,7 +105,8 @@
/// are no dependants to register with.
extern RegisterDependenciesFunction NoDependenciesToRegister;
-/// Used to notify a VSO that the given set of symbols failed to materialize.
+/// Used to notify a JITDylib that the given set of symbols failed to
+/// materialize.
class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
public:
static char ID;
@@ -114,57 +134,81 @@
SymbolNameSet Symbols;
};
+/// Used to notify clients that a set of symbols could not be removed.
+class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
+public:
+ static char ID;
+
+ SymbolsCouldNotBeRemoved(SymbolNameSet Symbols);
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const SymbolNameSet &getSymbols() const { return Symbols; }
+
+private:
+ SymbolNameSet Symbols;
+};
+
/// Tracks responsibility for materialization, and mediates interactions between
-/// MaterializationUnits and VSOs.
+/// MaterializationUnits and JDs.
///
/// An instance of this class is passed to MaterializationUnits when their
/// materialize method is called. It allows MaterializationUnits to resolve and
-/// finalize symbols, or abandon materialization by notifying any unmaterialized
+/// emit symbols, or abandon materialization by notifying any unmaterialized
/// symbols of an error.
class MaterializationResponsibility {
friend class MaterializationUnit;
public:
MaterializationResponsibility(MaterializationResponsibility &&) = default;
MaterializationResponsibility &
- operator=(MaterializationResponsibility &&) = default;
+ operator=(MaterializationResponsibility &&) = delete;
/// Destruct a MaterializationResponsibility instance. In debug mode
/// this asserts that all symbols being tracked have been either
- /// finalized or notified of an error.
+ /// emitted or notified of an error.
~MaterializationResponsibility();
- /// Returns the target VSO that these symbols are being materialized
+ /// Returns the target JITDylib that these symbols are being materialized
/// into.
- VSO &getTargetVSO() const { return V; }
+ JITDylib &getTargetJITDylib() const { return JD; }
/// Returns the symbol flags map for this responsibility instance.
- SymbolFlagsMap getSymbols() { return SymbolFlags; }
+ /// Note: The returned flags may have transient flags (Lazy, Materializing)
+ /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
+ /// before using.
+ const SymbolFlagsMap &getSymbols() { return SymbolFlags; }
/// Returns the names of any symbols covered by this
/// MaterializationResponsibility object that have queries pending. This
/// information can be used to return responsibility for unrequested symbols
- /// back to the VSO via the delegate method.
- SymbolNameSet getRequestedSymbols();
+ /// back to the JITDylib via the delegate method.
+ SymbolNameSet getRequestedSymbols() const;
- /// Resolves the given symbols. Individual calls to this method may
- /// resolve a subset of the symbols, but all symbols must have been
- /// resolved prior to calling finalize.
+ /// Notifies the target JITDylib that the given symbols have been resolved.
+ /// This will update the given symbols' addresses in the JITDylib, and notify
+ /// any pending queries on the given symbols of their resolution. The given
+ /// symbols must be ones covered by this MaterializationResponsibility
+ /// instance. Individual calls to this method may resolve a subset of the
+ /// symbols, but all symbols must have been resolved prior to calling emit.
void resolve(const SymbolMap &Symbols);
- /// Finalizes all symbols tracked by this instance.
- void finalize();
+ /// Notifies the target JITDylib (and any pending queries on that JITDylib)
+ /// that all symbols covered by this MaterializationResponsibility instance
+ /// have been emitted.
+ void emit();
- /// Adds new symbols to the VSO and this responsibility instance.
- /// VSO entries start out in the materializing state.
+ /// Adds new symbols to the JITDylib and this responsibility instance.
+ /// JITDylib entries start out in the materializing state.
///
/// This method can be used by materialization units that want to add
/// additional symbols at materialization time (e.g. stubs, compile
/// callbacks, metadata).
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
- /// Notify all unfinalized symbols that an error has occurred.
+ /// Notify all not-yet-emitted covered by this MaterializationResponsibility
+ /// instance that an error has occurred.
/// This will remove all symbols covered by this MaterializationResponsibilty
- /// from V, and send an error to any queries waiting on these symbols.
+ /// from the target JITDylib, and send an error to any queries waiting on
+ /// these symbols.
void failMaterialization();
/// Transfers responsibility to the given MaterializationUnit for all
@@ -186,11 +230,11 @@
void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
private:
- /// Create a MaterializationResponsibility for the given VSO and
+ /// Create a MaterializationResponsibility for the given JITDylib and
/// initial symbols.
- MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
+ MaterializationResponsibility(JITDylib &JD, SymbolFlagsMap SymbolFlags);
- VSO &V;
+ JITDylib &JD;
SymbolFlagsMap SymbolFlags;
};
@@ -199,9 +243,9 @@
/// overriding definitions are encountered).
///
/// MaterializationUnits are used when providing lazy definitions of symbols to
-/// VSOs. The VSO will call materialize when the address of a symbol is
-/// requested via the lookup method. The VSO will call discard if a stronger
-/// definition is added or already present.
+/// JITDylibs. The JITDylib will call materialize when the address of a symbol
+/// is requested via the lookup method. The JITDylib will call discard if a
+/// stronger definition is added or already present.
class MaterializationUnit {
public:
MaterializationUnit(SymbolFlagsMap InitalSymbolFlags)
@@ -209,21 +253,25 @@
virtual ~MaterializationUnit() {}
+ /// Return the name of this materialization unit. Useful for debugging
+ /// output.
+ virtual StringRef getName() const = 0;
+
/// Return the set of symbols that this source provides.
const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
/// Called by materialization dispatchers (see
/// ExecutionSession::DispatchMaterializationFunction) to trigger
/// materialization of this MaterializationUnit.
- void doMaterialize(VSO &V) {
- materialize(MaterializationResponsibility(V, std::move(SymbolFlags)));
+ void doMaterialize(JITDylib &JD) {
+ materialize(MaterializationResponsibility(JD, std::move(SymbolFlags)));
}
- /// Called by VSOs to notify MaterializationUnits that the given symbol has
- /// been overridden.
- void doDiscard(const VSO &V, SymbolStringPtr Name) {
+ /// Called by JITDylibs to notify MaterializationUnits that the given symbol
+ /// has been overridden.
+ void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
SymbolFlags.erase(Name);
- discard(V, std::move(Name));
+ discard(JD, std::move(Name));
}
protected:
@@ -241,7 +289,7 @@
/// from the source (e.g. if the source is an LLVM IR Module and the
/// symbol is a function, delete the function body or mark it available
/// externally).
- virtual void discard(const VSO &V, SymbolStringPtr Name) = 0;
+ virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
};
using MaterializationUnitList =
@@ -255,21 +303,23 @@
public:
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
+ StringRef getName() const override;
+
private:
void materialize(MaterializationResponsibility R) override;
- void discard(const VSO &V, SymbolStringPtr Name) override;
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
SymbolMap Symbols;
};
/// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
-/// Useful for inserting absolute symbols into a VSO. E.g.:
+/// Useful for inserting absolute symbols into a JITDylib. E.g.:
/// \code{.cpp}
-/// VSO &V = ...;
+/// JITDylib &JD = ...;
/// SymbolStringPtr Foo = ...;
/// JITEvaluatedSymbol FooSym = ...;
-/// if (auto Err = V.define(absoluteSymbols({{Foo, FooSym}})))
+/// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
/// return Err;
/// \endcode
///
@@ -295,32 +345,33 @@
/// aliased with alternate flags.
class ReExportsMaterializationUnit : public MaterializationUnit {
public:
- /// SourceVSO is allowed to be nullptr, in which case the source VSO is
- /// taken to be whatever VSO these definitions are materialized in. This
- /// is useful for defining aliases within a VSO.
+ /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
+ /// taken to be whatever JITDylib these definitions are materialized in. This
+ /// is useful for defining aliases within a JITDylib.
///
/// Note: Care must be taken that no sets of aliases form a cycle, as such
/// a cycle will result in a deadlock when any symbol in the cycle is
/// resolved.
- ReExportsMaterializationUnit(VSO *SourceVSO, SymbolAliasMap Aliases);
+ ReExportsMaterializationUnit(JITDylib *SourceJD, SymbolAliasMap Aliases);
+
+ StringRef getName() const override;
private:
void materialize(MaterializationResponsibility R) override;
- void discard(const VSO &V, SymbolStringPtr Name) override;
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
- VSO *SourceVSO = nullptr;
+ JITDylib *SourceJD = nullptr;
SymbolAliasMap Aliases;
};
/// Create a ReExportsMaterializationUnit with the given aliases.
-/// Useful for defining symbol aliases.: E.g., given a VSO V containing symbols
-/// "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" (for
-/// "bar") with:
-/// \code{.cpp}
+/// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
+/// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
+/// (for "bar") with: \code{.cpp}
/// SymbolStringPtr Baz = ...;
/// SymbolStringPtr Qux = ...;
-/// if (auto Err = V.define(symbolAliases({
+/// if (auto Err = JD.define(symbolAliases({
/// {Baz, { Foo, JITSymbolFlags::Exported }},
/// {Qux, { Bar, JITSymbolFlags::Weak }}}))
/// return Err;
@@ -331,169 +382,39 @@
std::move(Aliases));
}
-/// Create a materialization unit for re-exporting symbols from another VSO
+/// Create a materialization unit for re-exporting symbols from another JITDylib
/// with alternative names/flags.
inline std::unique_ptr<ReExportsMaterializationUnit>
-reexports(VSO &SourceV, SymbolAliasMap Aliases) {
- return llvm::make_unique<ReExportsMaterializationUnit>(&SourceV,
+reexports(JITDylib &SourceJD, SymbolAliasMap Aliases) {
+ return llvm::make_unique<ReExportsMaterializationUnit>(&SourceJD,
std::move(Aliases));
}
/// Build a SymbolAliasMap for the common case where you want to re-export
-/// symbols from another VSO with the same linkage/flags.
+/// symbols from another JITDylib with the same linkage/flags.
Expected<SymbolAliasMap>
-buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols);
+buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
class ReexportsFallbackDefinitionGenerator {
public:
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
- ReexportsFallbackDefinitionGenerator(VSO &BackingVSO, SymbolPredicate Allow);
- SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+ ReexportsFallbackDefinitionGenerator(JITDylib &BackingJD,
+ SymbolPredicate Allow);
+ SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
private:
- VSO &BackingVSO;
+ JITDylib &BackingJD;
SymbolPredicate Allow;
};
-/// Base utilities for ExecutionSession.
-class ExecutionSessionBase {
- // FIXME: Remove this when we remove the old ORC layers.
- friend class VSO;
-
-public:
- /// For reporting errors.
- using ErrorReporter = std::function<void(Error)>;
-
- /// For dispatching MaterializationUnit::materialize calls.
- using DispatchMaterializationFunction =
- std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
-
- /// Construct an ExecutionSessionBase.
- ///
- /// SymbolStringPools may be shared between ExecutionSessions.
- ExecutionSessionBase(std::shared_ptr<SymbolStringPool> SSP = nullptr)
- : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
-
- /// Returns the SymbolStringPool for this ExecutionSession.
- SymbolStringPool &getSymbolStringPool() const { return *SSP; }
-
- /// Run the given lambda with the session mutex locked.
- template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
- std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
- return F();
- }
-
- /// Set the error reporter function.
- ExecutionSessionBase &setErrorReporter(ErrorReporter ReportError) {
- this->ReportError = std::move(ReportError);
- return *this;
- }
-
- /// Set the materialization dispatch function.
- ExecutionSessionBase &setDispatchMaterialization(
- DispatchMaterializationFunction DispatchMaterialization) {
- this->DispatchMaterialization = std::move(DispatchMaterialization);
- return *this;
- }
-
- /// Report a error for this execution session.
- ///
- /// Unhandled errors can be sent here to log them.
- void reportError(Error Err) { ReportError(std::move(Err)); }
-
- /// Allocate a module key for a new module to add to the JIT.
- VModuleKey allocateVModule() { return ++LastKey; }
-
- /// Return a module key to the ExecutionSession so that it can be
- /// re-used. This should only be done once all resources associated
- /// with the original key have been released.
- void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
- }
-
- void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
-
- using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
- std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
-
- /// A legacy lookup function for JITSymbolResolverAdapter.
- /// Do not use -- this will be removed soon.
- Expected<SymbolMap>
- legacyLookup(ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup,
- SymbolNameSet Names, bool WaiUntilReady,
- RegisterDependenciesFunction RegisterDependencies);
-
- /// Search the given VSO list for the given symbols.
- ///
- ///
- /// The OnResolve callback will be called once all requested symbols are
- /// resolved, or if an error occurs prior to resolution.
- ///
- /// The OnReady callback will be called once all requested symbols are ready,
- /// or if an error occurs after resolution but before all symbols are ready.
- ///
- /// If all symbols are found, the RegisterDependencies function will be called
- /// while the session lock is held. This gives clients a chance to register
- /// dependencies for on the queried symbols for any symbols they are
- /// materializing (if a MaterializationResponsibility instance is present,
- /// this can be implemented by calling
- /// MaterializationResponsibility::addDependencies). If there are no
- /// dependenant symbols for this query (e.g. it is being made by a top level
- /// client to get an address to call) then the value NoDependenciesToRegister
- /// can be used.
- void lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
- SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
- RegisterDependenciesFunction RegisterDependencies);
-
- /// Blocking version of lookup above. Returns the resolved symbol map.
- /// If WaitUntilReady is true (the default), will not return until all
- /// requested symbols are ready (or an error occurs). If WaitUntilReady is
- /// false, will return as soon as all requested symbols are resolved,
- /// or an error occurs. If WaitUntilReady is false and an error occurs
- /// after resolution, the function will return a success value, but the
- /// error will be reported via reportErrors.
- Expected<SymbolMap> lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
- RegisterDependenciesFunction RegisterDependencies,
- bool WaitUntilReady = true);
-
- /// Materialize the given unit.
- void dispatchMaterialization(VSO &V,
- std::unique_ptr<MaterializationUnit> MU) {
- DispatchMaterialization(V, std::move(MU));
- }
-
-private:
- static void logErrorsToStdErr(Error Err) {
- logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
- }
-
- static void
- materializeOnCurrentThread(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
- MU->doMaterialize(V);
- }
-
- void runOutstandingMUs();
-
- mutable std::recursive_mutex SessionMutex;
- std::shared_ptr<SymbolStringPool> SSP;
- VModuleKey LastKey = 0;
- ErrorReporter ReportError = logErrorsToStdErr;
- DispatchMaterializationFunction DispatchMaterialization =
- materializeOnCurrentThread;
-
- // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
- // with callbacks from asynchronous queries.
- mutable std::recursive_mutex OutstandingMUsMutex;
- std::vector<std::pair<VSO *, std::unique_ptr<MaterializationUnit>>>
- OutstandingMUs;
-};
-
/// A symbol query that returns results via a callback when results are
/// ready.
///
/// makes a callback when all symbols are available.
class AsynchronousSymbolQuery {
- friend class ExecutionSessionBase;
- friend class VSO;
+ friend class ExecutionSession;
+ friend class JITDylib;
+ friend class JITSymbolResolverAdapter;
public:
@@ -528,9 +449,9 @@
void handleFullyReady();
private:
- void addQueryDependence(VSO &V, SymbolStringPtr Name);
+ void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
- void removeQueryDependence(VSO &V, const SymbolStringPtr &Name);
+ void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
bool canStillFail();
@@ -550,110 +471,116 @@
///
/// Represents a virtual shared object. Instances can not be copied or moved, so
/// their addresses may be used as keys for resource management.
-/// VSO state changes must be made via an ExecutionSession to guarantee that
-/// they are synchronized with respect to other VSO operations.
-class VSO {
+/// JITDylib state changes must be made via an ExecutionSession to guarantee
+/// that they are synchronized with respect to other JITDylib operations.
+class JITDylib {
friend class AsynchronousSymbolQuery;
friend class ExecutionSession;
- friend class ExecutionSessionBase;
friend class MaterializationResponsibility;
public:
- using FallbackDefinitionGeneratorFunction =
- std::function<SymbolNameSet(VSO &Parent, const SymbolNameSet &Names)>;
+ using FallbackDefinitionGeneratorFunction = std::function<SymbolNameSet(
+ JITDylib &Parent, const SymbolNameSet &Names)>;
using AsynchronousSymbolQuerySet =
std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
- VSO(const VSO &) = delete;
- VSO &operator=(const VSO &) = delete;
- VSO(VSO &&) = delete;
- VSO &operator=(VSO &&) = delete;
+ JITDylib(const JITDylib &) = delete;
+ JITDylib &operator=(const JITDylib &) = delete;
+ JITDylib(JITDylib &&) = delete;
+ JITDylib &operator=(JITDylib &&) = delete;
- /// Get the name for this VSO.
- const std::string &getName() const { return VSOName; }
+ /// Get the name for this JITDylib.
+ const std::string &getName() const { return JITDylibName; }
- /// Get a reference to the ExecutionSession for this VSO.
- ExecutionSessionBase &getExecutionSession() const { return ES; }
+ /// Get a reference to the ExecutionSession for this JITDylib.
+ ExecutionSession &getExecutionSession() const { return ES; }
/// Set a fallback defenition generator. If set, lookup and lookupFlags will
/// pass the unresolved symbols set to the fallback definition generator,
- /// allowing it to add a new definition to the VSO.
+ /// allowing it to add a new definition to the JITDylib.
void setFallbackDefinitionGenerator(
FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) {
this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator);
}
- /// Set the search order to be used when fixing up definitions in VSO.
+ /// 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
- /// resolutions made for definitions in this VSO after the call to
+ /// resolutions made for definitions in this JITDylib after the call to
/// setSearchOrder (even if the definition itself was added before the
/// call).
///
- /// If SearchThisVSOFirst is set, which by default it is, then this VSO will
- /// add itself to the beginning of the SearchOrder (Clients should *not*
- /// put this VSO in the list in this case, to avoid redundant lookups).
+ /// If SearchThisJITDylibFirst is set, which by default it is, then this
+ /// JITDylib will add itself to the beginning of the SearchOrder (Clients
+ /// should *not* put this JITDylib in the list in this case, to avoid
+ /// redundant lookups).
///
- /// If SearchThisVSOFirst is false then the search order will be used as
+ /// If SearchThisJITDylibFirst is false then the search order will be used as
/// given. The main motivation for this feature is to support deliberate
- /// shadowing of symbols in this VSO by a facade VSO. For example, the
- /// facade may resolve function names to stubs, and the stubs may compile
+ /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
+ /// the facade may resolve function names to stubs, and the stubs may compile
/// lazily by looking up symbols in this dylib. Adding the facade dylib
/// as the first in the search order (instead of this dylib) ensures that
/// definitions within this dylib resolve to the lazy-compiling stubs,
/// rather than immediately materializing the definitions in this dylib.
- void setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst = true);
+ void setSearchOrder(JITDylibList NewSearchOrder,
+ bool SearchThisJITDylibFirst = true);
- /// Add the given VSO to the search order for definitions in this VSO.
- void addToSearchOrder(VSO &V);
+ /// Add the given JITDylib to the search order for definitions in this
+ /// JITDylib.
+ void addToSearchOrder(JITDylib &JD);
- /// Replace OldV with NewV in the search order if OldV is present. Otherwise
- /// this operation is a no-op.
- void replaceInSearchOrder(VSO &OldV, VSO &NewV);
+ /// Replace OldJD with NewJD in the search order if OldJD is present.
+ /// Otherwise this operation is a no-op.
+ void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD);
- /// Remove the given VSO from the search order for this VSO if it is
+ /// Remove the given JITDylib from the search order for this JITDylib if it is
/// present. Otherwise this operation is a no-op.
- void removeFromSearchOrder(VSO &V);
+ void removeFromSearchOrder(JITDylib &JD);
/// Do something with the search order (run under the session lock).
template <typename Func>
auto withSearchOrderDo(Func &&F)
- -> decltype(F(std::declval<const VSOList &>())) {
- return ES.runSessionLocked([&]() { return F(SearchOrder); });
- }
+ -> decltype(F(std::declval<const JITDylibList &>()));
- /// Define all symbols provided by the materialization unit to be part
- /// of the given VSO.
- template <typename UniquePtrToMaterializationUnit>
- typename std::enable_if<
- std::is_convertible<
- typename std::decay<UniquePtrToMaterializationUnit>::type,
- std::unique_ptr<MaterializationUnit>>::value,
- Error>::type
- define(UniquePtrToMaterializationUnit &&MU) {
- return ES.runSessionLocked([&, this]() -> Error {
- assert(MU && "Can't define with a null MU");
+ /// Define all symbols provided by the materialization unit to be part of this
+ /// JITDylib.
+ ///
+ /// This overload always takes ownership of the MaterializationUnit. If any
+ /// errors occur, the MaterializationUnit consumed.
+ template <typename MaterializationUnitType>
+ Error define(std::unique_ptr<MaterializationUnitType> &&MU);
- if (auto Err = defineImpl(*MU))
- return Err;
+ /// Define all symbols provided by the materialization unit to be part of this
+ /// JITDylib.
+ ///
+ /// This overload only takes ownership of the MaterializationUnit no error is
+ /// generated. If an error occurs, ownership remains with the caller. This
+ /// may allow the caller to modify the MaterializationUnit to correct the
+ /// issue, then re-call define.
+ template <typename MaterializationUnitType>
+ Error define(std::unique_ptr<MaterializationUnitType> &MU);
- /// defineImpl succeeded.
- auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
- for (auto &KV : UMI->MU->getSymbols())
- UnmaterializedInfos[KV.first] = UMI;
+ /// Tries to remove the given symbols.
+ ///
+ /// If any symbols are not defined in this JITDylib this method will return
+ /// a SymbolsNotFound error covering the missing symbols.
+ ///
+ /// If all symbols are found but some symbols are in the process of being
+ /// materialized this method will return a SymbolsCouldNotBeRemoved error.
+ ///
+ /// On success, all symbols are removed. On failure, the JITDylib state is
+ /// left unmodified (no symbols are removed).
+ Error remove(const SymbolNameSet &Names);
- return Error::success();
- });
- }
-
- /// Search the given VSO for the symbols in Symbols. If found, store
+ /// Search the given JITDylib for the symbols in Symbols. If found, store
/// the flags for each symbol in Flags. Returns any unresolved symbols.
SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
- /// Dump current VSO state to OS.
+ /// Dump current JITDylib state to OS.
void dump(raw_ostream &OS);
/// FIXME: Remove this when we remove the old ORC layers.
- /// Search the given VSOs in order for the symbols in Symbols. Results
+ /// Search the given JITDylibs in order for the symbols in Symbols. Results
/// (once they become available) will be returned via the given Query.
///
/// If any symbol is not found then the unresolved symbols will be returned,
@@ -680,8 +607,8 @@
struct MaterializingInfo {
AsynchronousSymbolQueryList PendingQueries;
SymbolDependenceMap Dependants;
- SymbolDependenceMap UnfinalizedDependencies;
- bool IsFinalized = false;
+ SymbolDependenceMap UnemittedDependencies;
+ bool IsEmitted = false;
};
using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
@@ -693,7 +620,7 @@
LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
};
- VSO(ExecutionSessionBase &ES, std::string Name);
+ JITDylib(ExecutionSession &ES, std::string Name);
Error defineImpl(MaterializationUnit &MU);
@@ -714,77 +641,263 @@
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);
- void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
- const SymbolStringPtr &DependantName,
- MaterializingInfo &FinalizedMI);
+ void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
+ const SymbolStringPtr &DependantName,
+ MaterializingInfo &EmittedMI);
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
void replace(std::unique_ptr<MaterializationUnit> MU);
- SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
+ SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependants);
void resolve(const SymbolMap &Resolved);
- void finalize(const SymbolFlagsMap &Finalized);
+ void emit(const SymbolFlagsMap &Emitted);
void notifyFailed(const SymbolNameSet &FailedSymbols);
- ExecutionSessionBase &ES;
- std::string VSOName;
+ ExecutionSession &ES;
+ std::string JITDylibName;
SymbolMap Symbols;
UnmaterializedInfosMap UnmaterializedInfos;
MaterializingInfosMap MaterializingInfos;
FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
- VSOList SearchOrder;
+ JITDylibList SearchOrder;
};
/// An ExecutionSession represents a running JIT program.
-class ExecutionSession : public ExecutionSessionBase {
+class ExecutionSession {
+ // FIXME: Remove this when we remove the old ORC layers.
+ friend class JITDylib;
+
public:
+ /// For reporting errors.
using ErrorReporter = std::function<void(Error)>;
- using DispatchMaterializationFunction =
- std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
+ /// For dispatching MaterializationUnit::materialize calls.
+ using DispatchMaterializationFunction = std::function<void(
+ JITDylib &JD, std::unique_ptr<MaterializationUnit> MU)>;
- /// Construct an ExecutionEngine.
+ /// Construct an ExecutionSession.
///
/// SymbolStringPools may be shared between ExecutionSessions.
- ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr)
- : ExecutionSessionBase(std::move(SSP)) {}
+ ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
- /// Add a new VSO to this ExecutionSession.
- VSO &createVSO(std::string Name);
+ /// Add a symbol name to the SymbolStringPool and return a pointer to it.
+ SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
+
+ /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
+ std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
+
+ /// Run the given lambda with the session mutex locked.
+ template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
+ std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
+ return F();
+ }
+
+ /// Get the "main" JITDylib, which is created automatically on construction of
+ /// the ExecutionSession.
+ JITDylib &getMainJITDylib();
+
+ /// Add a new JITDylib to this ExecutionSession.
+ JITDylib &createJITDylib(std::string Name,
+ bool AddToMainDylibSearchOrder = true);
+
+ /// Allocate a module key for a new module to add to the JIT.
+ VModuleKey allocateVModule() {
+ return runSessionLocked([this]() { return ++LastKey; });
+ }
+
+ /// Return a module key to the ExecutionSession so that it can be
+ /// re-used. This should only be done once all resources associated
+ /// with the original key have been released.
+ void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
+ }
+
+ /// Set the error reporter function.
+ ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
+ this->ReportError = std::move(ReportError);
+ return *this;
+ }
+
+ /// Report a error for this execution session.
+ ///
+ /// Unhandled errors can be sent here to log them.
+ void reportError(Error Err) { ReportError(std::move(Err)); }
+
+ /// Set the materialization dispatch function.
+ ExecutionSession &setDispatchMaterialization(
+ DispatchMaterializationFunction DispatchMaterialization) {
+ this->DispatchMaterialization = std::move(DispatchMaterialization);
+ return *this;
+ }
+
+ void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
+
+ using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
+ std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
+
+ /// A legacy lookup function for JITSymbolResolverAdapter.
+ /// Do not use -- this will be removed soon.
+ Expected<SymbolMap>
+ legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
+ bool WaiUntilReady,
+ RegisterDependenciesFunction RegisterDependencies);
+
+ /// Search the given JITDylib list for the given symbols.
+ ///
+ ///
+ /// The OnResolve callback will be called once all requested symbols are
+ /// resolved, or if an error occurs prior to resolution.
+ ///
+ /// The OnReady callback will be called once all requested symbols are ready,
+ /// or if an error occurs after resolution but before all symbols are ready.
+ ///
+ /// If all symbols are found, the RegisterDependencies function will be called
+ /// while the session lock is held. This gives clients a chance to register
+ /// dependencies for on the queried symbols for any symbols they are
+ /// materializing (if a MaterializationResponsibility instance is present,
+ /// this can be implemented by calling
+ /// MaterializationResponsibility::addDependencies). If there are no
+ /// dependenant symbols for this query (e.g. it is being made by a top level
+ /// client to get an address to call) then the value NoDependenciesToRegister
+ /// can be used.
+ void lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
+ SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
+ RegisterDependenciesFunction RegisterDependencies);
+
+ /// Blocking version of lookup above. Returns the resolved symbol map.
+ /// If WaitUntilReady is true (the default), will not return until all
+ /// requested symbols are ready (or an error occurs). If WaitUntilReady is
+ /// false, will return as soon as all requested symbols are resolved,
+ /// or an error occurs. If WaitUntilReady is false and an error occurs
+ /// after resolution, the function will return a success value, but the
+ /// error will be reported via reportErrors.
+ Expected<SymbolMap> lookup(const JITDylibList &JDs,
+ const SymbolNameSet &Symbols,
+ RegisterDependenciesFunction RegisterDependencies,
+ bool WaitUntilReady = true);
+
+ /// Convenience version of the blocking version of lookup above. Uses the main
+ /// JITDylib's search order as the lookup order, and registers no
+ /// dependencies.
+ Expected<SymbolMap> lookup(const SymbolNameSet &Symbols) {
+ return getMainJITDylib().withSearchOrderDo(
+ [&](const JITDylibList &SearchOrder) {
+ return lookup(SearchOrder, Symbols, NoDependenciesToRegister, true);
+ });
+ }
+
+ /// Materialize the given unit.
+ void dispatchMaterialization(JITDylib &JD,
+ std::unique_ptr<MaterializationUnit> MU) {
+ LLVM_DEBUG(runSessionLocked([&]() {
+ dbgs() << "Compiling, for " << JD.getName() << ", " << *MU
+ << "\n";
+ }););
+ DispatchMaterialization(JD, std::move(MU));
+ }
+
+ /// Dump the state of all the JITDylibs in this session.
+ void dump(raw_ostream &OS);
private:
- std::vector<std::unique_ptr<VSO>> VSOs;
+ static void logErrorsToStdErr(Error Err) {
+ logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
+ }
+
+ static void
+ materializeOnCurrentThread(JITDylib &JD,
+ std::unique_ptr<MaterializationUnit> MU) {
+ MU->doMaterialize(JD);
+ }
+
+ void runOutstandingMUs();
+
+ mutable std::recursive_mutex SessionMutex;
+ std::shared_ptr<SymbolStringPool> SSP;
+ VModuleKey LastKey = 0;
+ ErrorReporter ReportError = logErrorsToStdErr;
+ DispatchMaterializationFunction DispatchMaterialization =
+ materializeOnCurrentThread;
+
+ std::vector<std::unique_ptr<JITDylib>> JDs;
+
+ // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
+ // with callbacks from asynchronous queries.
+ mutable std::recursive_mutex OutstandingMUsMutex;
+ std::vector<std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>>>
+ OutstandingMUs;
};
-/// Look up the given names in the given VSOs.
-/// VSOs will be searched in order and no VSO pointer may be null.
-/// All symbols must be found within the given VSOs or an error
-/// will be returned.
-Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names);
+template <typename Func>
+auto JITDylib::withSearchOrderDo(Func &&F)
+ -> decltype(F(std::declval<const JITDylibList &>())) {
+ return ES.runSessionLocked([&]() { return F(SearchOrder); });
+}
-/// Look up a symbol by searching a list of VSOs.
-Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name);
+template <typename MaterializationUnitType>
+Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
+ assert(MU && "Can not define with a null MU");
+ return ES.runSessionLocked([&, this]() -> Error {
+ if (auto Err = defineImpl(*MU))
+ return Err;
+
+ /// defineImpl succeeded.
+ auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
+ for (auto &KV : UMI->MU->getSymbols())
+ UnmaterializedInfos[KV.first] = UMI;
+
+ return Error::success();
+ });
+}
+
+template <typename MaterializationUnitType>
+Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
+ assert(MU && "Can not define with a null MU");
+
+ return ES.runSessionLocked([&, this]() -> Error {
+ if (auto Err = defineImpl(*MU))
+ return Err;
+
+ /// defineImpl succeeded.
+ auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
+ for (auto &KV : UMI->MU->getSymbols())
+ UnmaterializedInfos[KV.first] = UMI;
+
+ return Error::success();
+ });
+}
+
+/// Look up the given names in the given JITDylibs.
+/// JDs will be searched in order and no JITDylib pointer may be null.
+/// All symbols must be found within the given JITDylibs or an error
+/// will be returned.
+Expected<SymbolMap> lookup(const JITDylibList &JDs, SymbolNameSet Names);
+
+/// Look up a symbol by searching a list of JITDylibs.
+Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs,
+ SymbolStringPtr Name);
/// Mangles symbol names then uniques them in the context of an
/// ExecutionSession.
class MangleAndInterner {
public:
- MangleAndInterner(ExecutionSessionBase &ES, const DataLayout &DL);
+ MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
SymbolStringPtr operator()(StringRef Name);
private:
- ExecutionSessionBase &ES;
+ ExecutionSession &ES;
const DataLayout &DL;
};
} // End namespace orc
} // End namespace llvm
+#undef DEBUG_TYPE // "orc"
+
#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index e27f6e1..5225066 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -21,7 +21,6 @@
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Target/TargetOptions.h"
#include <algorithm>
#include <cstdint>
#include <string>
@@ -39,45 +38,6 @@
namespace orc {
-/// A utility class for building TargetMachines for JITs.
-class JITTargetMachineBuilder {
-public:
- JITTargetMachineBuilder(Triple TT);
- static Expected<JITTargetMachineBuilder> detectHost();
- Expected<std::unique_ptr<TargetMachine>> createTargetMachine();
-
- JITTargetMachineBuilder &setArch(std::string Arch) {
- this->Arch = std::move(Arch);
- return *this;
- }
- JITTargetMachineBuilder &setCPU(std::string CPU) {
- this->CPU = std::move(CPU);
- return *this;
- }
- JITTargetMachineBuilder &setRelocationModel(Optional<Reloc::Model> RM) {
- this->RM = std::move(RM);
- return *this;
- }
- JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) {
- this->CM = std::move(CM);
- return *this;
- }
- JITTargetMachineBuilder &
- addFeatures(const std::vector<std::string> &FeatureVec);
- SubtargetFeatures &getFeatures() { return Features; }
- TargetOptions &getOptions() { return Options; }
-
-private:
- Triple TT;
- std::string Arch;
- std::string CPU;
- SubtargetFeatures Features;
- TargetOptions Options;
- Optional<Reloc::Model> RM;
- Optional<CodeModel::Model> CM;
- CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
-};
-
/// This iterator provides a convenient way to iterate over the elements
/// of an llvm.global_ctors/llvm.global_dtors instance.
///
@@ -171,7 +131,7 @@
class CtorDtorRunner2 {
public:
- CtorDtorRunner2(VSO &V) : V(V) {}
+ CtorDtorRunner2(JITDylib &JD) : JD(JD) {}
void add(iterator_range<CtorDtorIterator> CtorDtors);
Error run();
@@ -179,7 +139,7 @@
using CtorDtorList = std::vector<SymbolStringPtr>;
using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
- VSO &V;
+ JITDylib &JD;
CtorDtorPriorityMap CtorDtorsByPriority;
};
@@ -244,20 +204,44 @@
class LocalCXXRuntimeOverrides2 : public LocalCXXRuntimeOverridesBase {
public:
- Error enable(VSO &V, MangleAndInterner &Mangler);
+ Error enable(JITDylib &JD, MangleAndInterner &Mangler);
};
/// A utility class to expose symbols found via dlsym to the JIT.
///
-/// If an instance of this class is attached to a VSO as a fallback definition
-/// generator, then any symbol found in the given DynamicLibrary that passes
-/// the 'Allow' predicate will be added to the VSO.
+/// 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
+/// passes the 'Allow' predicate will be added to the JITDylib.
class DynamicLibraryFallbackGenerator {
public:
using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+
+ static bool AllowAll(SymbolStringPtr Name) { return true; }
+
+ /// Create a DynamicLibraryFallbackGenerator that searches for symbols in the
+ /// given sys::DynamicLibrary.
+ /// Only symbols that match the 'Allow' predicate will be searched for.
DynamicLibraryFallbackGenerator(sys::DynamicLibrary Dylib,
- const DataLayout &DL, SymbolPredicate Allow);
- SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+ const DataLayout &DL,
+ SymbolPredicate Allow = AllowAll);
+
+ /// Permanently loads the library at the given path and, on success, returns
+ /// a DynamicLibraryFallbackGenerator that will search it for symbol
+ /// definitions matching the Allow predicate.
+ /// On failure returns the reason the library failed to load.
+ static Expected<DynamicLibraryFallbackGenerator>
+ Load(const char *FileName, const DataLayout &DL,
+ SymbolPredicate Allow = AllowAll);
+
+ /// Creates a DynamicLibraryFallbackGenerator that searches for symbols in
+ /// the current process.
+ static Expected<DynamicLibraryFallbackGenerator>
+ CreateForCurrentProcess(const DataLayout &DL,
+ SymbolPredicate Allow = AllowAll) {
+ return Load(nullptr, DL, std::move(Allow));
+ }
+
+ SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
private:
sys::DynamicLibrary Dylib;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index ad64815..cb8df26 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -34,7 +34,7 @@
std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>;
using NotifyCompiledFunction =
- std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
+ std::function<void(VModuleKey K, ThreadSafeModule TSM)>;
IRCompileLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
CompileFunction Compile);
@@ -42,7 +42,7 @@
void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled);
void emit(MaterializationResponsibility R, VModuleKey K,
- std::unique_ptr<Module> M) override;
+ ThreadSafeModule TSM) override;
private:
mutable std::mutex IRLayerMutex;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
index 266a0f4..d5f91ce 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -25,9 +25,8 @@
class IRTransformLayer2 : public IRLayer {
public:
-
- using TransformFunction =
- std::function<Expected<std::unique_ptr<Module>>(std::unique_ptr<Module>)>;
+ using TransformFunction = std::function<Expected<ThreadSafeModule>(
+ ThreadSafeModule, const MaterializationResponsibility &R)>;
IRTransformLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
TransformFunction Transform = identityTransform);
@@ -37,10 +36,12 @@
}
void emit(MaterializationResponsibility R, VModuleKey K,
- std::unique_ptr<Module> M) override;
+ ThreadSafeModule TSM) override;
- static std::unique_ptr<Module> identityTransform(std::unique_ptr<Module> M) {
- return M;
+ static ThreadSafeModule
+ identityTransform(ThreadSafeModule TSM,
+ const MaterializationResponsibility &R) {
+ return TSM;
}
private:
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index 8b0b3fd..c252780 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -47,92 +47,101 @@
namespace orc {
-/// Target-independent base class for compile callback management.
-class JITCompileCallbackManager {
+/// Base class for pools of compiler re-entry trampolines.
+/// These trampolines are callable addresses that save all register state
+/// before calling a supplied function to return the trampoline landing
+/// address, then restore all state before jumping to that address. They
+/// are used by various ORC APIs to support lazy compilation
+class TrampolinePool {
public:
- using CompileFunction = std::function<JITTargetAddress()>;
+ virtual ~TrampolinePool() {}
- /// Construct a JITCompileCallbackManager.
- /// @param ErrorHandlerAddress The address of an error handler in the target
- /// process to be used if a compile callback fails.
- JITCompileCallbackManager(ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress)
- : ES(ES), CallbacksVSO(ES.createVSO("<Callbacks>")),
- ErrorHandlerAddress(ErrorHandlerAddress) {}
-
- virtual ~JITCompileCallbackManager() = default;
-
- /// Reserve a compile callback.
- Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
-
- /// Execute the callback for the given trampoline id. Called by the JIT
- /// to compile functions on demand.
- JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
-
-protected:
- std::vector<JITTargetAddress> AvailableTrampolines;
+ /// Get an available trampoline address.
+ /// Returns an error if no trampoline can be created.
+ virtual Expected<JITTargetAddress> getTrampoline() = 0;
private:
- Expected<JITTargetAddress> getAvailableTrampolineAddr() {
- if (this->AvailableTrampolines.empty())
+ virtual void anchor();
+};
+
+/// A trampoline pool for trampolines within the current process.
+template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
+public:
+ using GetTrampolineLandingFunction =
+ std::function<JITTargetAddress(JITTargetAddress TrampolineAddr)>;
+
+ /// Creates a LocalTrampolinePool with the given RunCallback function.
+ /// Returns an error if this function is unable to correctly allocate, write
+ /// and protect the resolver code block.
+ static Expected<std::unique_ptr<LocalTrampolinePool>>
+ Create(GetTrampolineLandingFunction GetTrampolineLanding) {
+ Error Err = Error::success();
+
+ auto LTP = std::unique_ptr<LocalTrampolinePool>(
+ new LocalTrampolinePool(std::move(GetTrampolineLanding), Err));
+
+ if (Err)
+ return std::move(Err);
+ return std::move(LTP);
+ }
+
+ /// Get a free trampoline. Returns an error if one can not be provide (e.g.
+ /// because the pool is empty and can not be grown).
+ Expected<JITTargetAddress> getTrampoline() override {
+ std::lock_guard<std::mutex> Lock(LTPMutex);
+ if (AvailableTrampolines.empty()) {
if (auto Err = grow())
return std::move(Err);
- assert(!this->AvailableTrampolines.empty() &&
- "Failed to grow available trampolines.");
- JITTargetAddress TrampolineAddr = this->AvailableTrampolines.back();
- this->AvailableTrampolines.pop_back();
+ }
+ assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
+ auto TrampolineAddr = AvailableTrampolines.back();
+ AvailableTrampolines.pop_back();
return TrampolineAddr;
}
- // Create new trampolines - to be implemented in subclasses.
- virtual Error grow() = 0;
+ /// Returns the given trampoline to the pool for re-use.
+ void releaseTrampoline(JITTargetAddress TrampolineAddr) {
+ std::lock_guard<std::mutex> Lock(LTPMutex);
+ AvailableTrampolines.push_back(TrampolineAddr);
+ }
- virtual void anchor();
+private:
+ static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
+ LocalTrampolinePool<ORCABI> *TrampolinePool =
+ static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
+ return TrampolinePool->GetTrampolineLanding(static_cast<JITTargetAddress>(
+ reinterpret_cast<uintptr_t>(TrampolineId)));
+ }
- std::mutex CCMgrMutex;
- ExecutionSession &ES;
- VSO &CallbacksVSO;
- JITTargetAddress ErrorHandlerAddress;
- std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
- size_t NextCallbackId = 0;
-};
+ LocalTrampolinePool(GetTrampolineLandingFunction GetTrampolineLanding,
+ Error &Err)
+ : GetTrampolineLanding(std::move(GetTrampolineLanding)) {
-/// Manage compile callbacks for in-process JITs.
-template <typename TargetT>
-class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
-public:
- /// Construct a InProcessJITCompileCallbackManager.
- /// @param ErrorHandlerAddress The address of an error handler in the target
- /// process to be used if a compile callback fails.
- LocalJITCompileCallbackManager(ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ES, ErrorHandlerAddress) {
- /// Set up the resolver block.
+ ErrorAsOutParameter _(&Err);
+
+ /// Try to set up the resolver block.
std::error_code EC;
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
- TargetT::ResolverCodeSize, nullptr,
+ ORCABI::ResolverCodeSize, nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
- assert(!EC && "Failed to allocate resolver block");
+ if (EC) {
+ Err = errorCodeToError(EC);
+ return;
+ }
- TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
- &reenter, this);
+ ORCABI::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
+ &reenter, this);
EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
sys::Memory::MF_READ |
sys::Memory::MF_EXEC);
- assert(!EC && "Failed to mprotect resolver block");
+ if (EC) {
+ Err = errorCodeToError(EC);
+ return;
+ }
}
-private:
- static JITTargetAddress reenter(void *CCMgr, void *TrampolineId) {
- JITCompileCallbackManager *Mgr =
- static_cast<JITCompileCallbackManager *>(CCMgr);
- return Mgr->executeCompileCallback(
- static_cast<JITTargetAddress>(
- reinterpret_cast<uintptr_t>(TrampolineId)));
- }
-
- Error grow() override {
+ Error grow() {
assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
std::error_code EC;
@@ -144,17 +153,17 @@
return errorCodeToError(EC);
unsigned NumTrampolines =
- (sys::Process::getPageSize() - TargetT::PointerSize) /
- TargetT::TrampolineSize;
+ (sys::Process::getPageSize() - ORCABI::PointerSize) /
+ ORCABI::TrampolineSize;
uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
- TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
- NumTrampolines);
+ ORCABI::writeTrampolines(TrampolineMem, ResolverBlock.base(),
+ NumTrampolines);
for (unsigned I = 0; I < NumTrampolines; ++I)
this->AvailableTrampolines.push_back(
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(
- TrampolineMem + (I * TargetT::TrampolineSize))));
+ TrampolineMem + (I * ORCABI::TrampolineSize))));
if (auto EC = sys::Memory::protectMappedMemory(
TrampolineBlock.getMemoryBlock(),
@@ -165,8 +174,87 @@
return Error::success();
}
+ GetTrampolineLandingFunction GetTrampolineLanding;
+
+ std::mutex LTPMutex;
sys::OwningMemoryBlock ResolverBlock;
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
+ std::vector<JITTargetAddress> AvailableTrampolines;
+};
+
+/// Target-independent base class for compile callback management.
+class JITCompileCallbackManager {
+public:
+ using CompileFunction = std::function<JITTargetAddress()>;
+
+ virtual ~JITCompileCallbackManager() = default;
+
+ /// Reserve a compile callback.
+ Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
+
+ /// Execute the callback for the given trampoline id. Called by the JIT
+ /// to compile functions on demand.
+ JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
+
+protected:
+ /// Construct a JITCompileCallbackManager.
+ JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,
+ ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : TP(std::move(TP)), ES(ES),
+ CallbacksJD(ES.createJITDylib("<Callbacks>")),
+ ErrorHandlerAddress(ErrorHandlerAddress) {}
+
+ void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
+ this->TP = std::move(TP);
+ }
+
+private:
+ std::mutex CCMgrMutex;
+ std::unique_ptr<TrampolinePool> TP;
+ ExecutionSession &ES;
+ JITDylib &CallbacksJD;
+ JITTargetAddress ErrorHandlerAddress;
+ std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
+ size_t NextCallbackId = 0;
+};
+
+/// Manage compile callbacks for in-process JITs.
+template <typename ORCABI>
+class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
+public:
+ /// Create a new LocalJITCompileCallbackManager.
+ static Expected<std::unique_ptr<LocalJITCompileCallbackManager>>
+ Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress) {
+ Error Err = Error::success();
+ auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
+ new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
+ if (Err)
+ return std::move(Err);
+ return std::move(CCMgr);
+ }
+
+private:
+ /// Construct a InProcessJITCompileCallbackManager.
+ /// @param ErrorHandlerAddress The address of an error handler in the target
+ /// process to be used if a compile callback fails.
+ LocalJITCompileCallbackManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress,
+ Error &Err)
+ : JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
+ ErrorAsOutParameter _(&Err);
+ auto TP = LocalTrampolinePool<ORCABI>::Create(
+ [this](JITTargetAddress TrampolineAddr) {
+ return executeCompileCallback(TrampolineAddr);
+ });
+
+ if (!TP) {
+ Err = TP.takeError();
+ return;
+ }
+
+ setTrampolinePool(std::move(*TP));
+ }
};
/// Base class for managing collections of named indirect stubs.
@@ -207,6 +295,7 @@
public:
Error createStub(StringRef StubName, JITTargetAddress StubAddr,
JITSymbolFlags StubFlags) override {
+ std::lock_guard<std::mutex> Lock(StubsMutex);
if (auto Err = reserveStubs(1))
return Err;
@@ -216,6 +305,7 @@
}
Error createStubs(const StubInitsMap &StubInits) override {
+ std::lock_guard<std::mutex> Lock(StubsMutex);
if (auto Err = reserveStubs(StubInits.size()))
return Err;
@@ -227,6 +317,7 @@
}
JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+ std::lock_guard<std::mutex> Lock(StubsMutex);
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
@@ -242,6 +333,7 @@
}
JITEvaluatedSymbol findPointer(StringRef Name) override {
+ std::lock_guard<std::mutex> Lock(StubsMutex);
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
@@ -254,11 +346,15 @@
}
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
+ using AtomicIntPtr = std::atomic<uintptr_t>;
+
+ std::lock_guard<std::mutex> Lock(StubsMutex);
auto I = StubIndexes.find(Name);
assert(I != StubIndexes.end() && "No stub pointer for symbol");
auto Key = I->second.first;
- *IndirectStubsInfos[Key.first].getPtr(Key.second) =
- reinterpret_cast<void *>(static_cast<uintptr_t>(NewAddr));
+ AtomicIntPtr *AtomicStubPtr = reinterpret_cast<AtomicIntPtr *>(
+ IndirectStubsInfos[Key.first].getPtr(Key.second));
+ *AtomicStubPtr = static_cast<uintptr_t>(NewAddr);
return Error::success();
}
@@ -288,6 +384,7 @@
StubIndexes[StubName] = std::make_pair(Key, StubFlags);
}
+ std::mutex StubsMutex;
std::vector<typename TargetT::IndirectStubsInfo> IndirectStubsInfos;
using StubKey = std::pair<uint16_t, uint16_t>;
std::vector<StubKey> FreeStubs;
@@ -299,7 +396,7 @@
/// The given target triple will determine the ABI, and the given
/// ErrorHandlerAddress will be used by the resulting compile callback
/// manager if a compile callback fails.
-std::unique_ptr<JITCompileCallbackManager>
+Expected<std::unique_ptr<JITCompileCallbackManager>>
createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress);
@@ -325,12 +422,18 @@
/// indirect call using the given function pointer.
void makeStub(Function &F, Value &ImplPointer);
-/// Raise linkage types and rename as necessary to ensure that all
-/// symbols are accessible for other modules.
-///
-/// This should be called before partitioning a module to ensure that the
-/// partitions retain access to each other's symbols.
-void makeAllSymbolsExternallyAccessible(Module &M);
+/// Promotes private symbols to global hidden, and renames to prevent clashes
+/// with other promoted symbols. The same SymbolPromoter instance should be
+/// used for all symbols to be added to a single JITDylib.
+class SymbolLinkagePromoter {
+public:
+ /// Promote symbols in the given module. Returns the set of global values
+ /// that have been renamed/promoted.
+ std::vector<GlobalValue *> operator()(Module &M);
+
+private:
+ unsigned NextId = 0;
+};
/// Clone a function declaration into a new module.
///
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
new file mode 100644
index 0000000..eb9b6bf
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
@@ -0,0 +1,130 @@
+//===- JITTargetMachineBuilder.h - Build TargetMachines for JIT -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A utitily for building TargetMachines for JITs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H
+#define LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+/// A utility class for building TargetMachines for JITs.
+class JITTargetMachineBuilder {
+public:
+ /// Create a JITTargetMachineBuilder based on the given triple.
+ ///
+ /// Note: TargetOptions is default-constructed, then EmulatedTLS and
+ /// ExplicitEmulatedTLS are set to true. If EmulatedTLS is not
+ /// required, these values should be reset before calling
+ /// createTargetMachine.
+ JITTargetMachineBuilder(Triple TT);
+
+ /// Create a JITTargetMachineBuilder for the host system.
+ ///
+ /// Note: TargetOptions is default-constructed, then EmulatedTLS and
+ /// ExplicitEmulatedTLS are set to true. If EmulatedTLS is not
+ /// required, these values should be reset before calling
+ /// createTargetMachine.
+ static Expected<JITTargetMachineBuilder> detectHost();
+
+ /// Create a TargetMachine.
+ ///
+ /// This operation will fail if the requested target is not registered,
+ /// in which case see llvm/Support/TargetSelect.h. To JIT IR the Target and
+ /// the target's AsmPrinter must both be registered. To JIT assembly
+ /// (including inline and module level assembly) the target's AsmParser must
+ /// also be registered.
+ Expected<std::unique_ptr<TargetMachine>> createTargetMachine();
+
+ /// Get the default DataLayout for the target.
+ ///
+ /// Note: This is reasonably expensive, as it creates a temporary
+ /// TargetMachine instance under the hood. It is only suitable for use during
+ /// JIT setup.
+ Expected<DataLayout> getDefaultDataLayoutForTarget() {
+ auto TM = createTargetMachine();
+ if (!TM)
+ return TM.takeError();
+ return (*TM)->createDataLayout();
+ }
+
+ /// Set the CPU string.
+ JITTargetMachineBuilder &setCPU(std::string CPU) {
+ this->CPU = std::move(CPU);
+ return *this;
+ }
+
+ /// Set the relocation model.
+ JITTargetMachineBuilder &setRelocationModel(Optional<Reloc::Model> RM) {
+ this->RM = std::move(RM);
+ return *this;
+ }
+
+ /// Set the code model.
+ JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) {
+ this->CM = std::move(CM);
+ return *this;
+ }
+
+ /// Set the LLVM CodeGen optimization level.
+ JITTargetMachineBuilder &setCodeGenOptLevel(CodeGenOpt::Level OptLevel) {
+ this->OptLevel = OptLevel;
+ return *this;
+ }
+
+ /// Add subtarget features.
+ JITTargetMachineBuilder &
+ addFeatures(const std::vector<std::string> &FeatureVec);
+
+ /// Access subtarget features.
+ SubtargetFeatures &getFeatures() { return Features; }
+
+ /// Access subtarget features.
+ const SubtargetFeatures &getFeatures() const { return Features; }
+
+ /// Access TargetOptions.
+ TargetOptions &getOptions() { return Options; }
+
+ /// Access TargetOptions.
+ const TargetOptions &getOptions() const { return Options; }
+
+ /// Access Triple.
+ Triple &getTargetTriple() { return TT; }
+
+ /// Access Triple.
+ const Triple &getTargetTriple() const { return TT; }
+
+private:
+ Triple TT;
+ std::string CPU;
+ SubtargetFeatures Features;
+ TargetOptions Options;
+ Optional<Reloc::Model> RM;
+ Optional<CodeModel::Model> CM;
+ CodeGenOpt::Level OptLevel = CodeGenOpt::None;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
index df655bd..400d4cb 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -19,9 +19,11 @@
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/Target/TargetMachine.h"
+#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/Support/ThreadPool.h"
namespace llvm {
namespace orc {
@@ -29,44 +31,63 @@
/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
class LLJIT {
public:
- /// Create an LLJIT instance.
- static Expected<std::unique_ptr<LLJIT>>
- Create(std::unique_ptr<ExecutionSession> ES,
- std::unique_ptr<TargetMachine> TM, DataLayout DL);
- /// Returns a reference to the ExecutionSession for this JIT instance.
+ /// Destruct this instance. If a multi-threaded instance, waits for all
+ /// compile threads to complete.
+ ~LLJIT();
+
+ /// Create an LLJIT instance.
+ /// If NumCompileThreads is not equal to zero, creates a multi-threaded
+ /// LLJIT with the given number of compile threads.
+ static Expected<std::unique_ptr<LLJIT>>
+ Create(JITTargetMachineBuilder JTMB, DataLayout DL,
+ unsigned NumCompileThreads = 0);
+
+ /// Returns the ExecutionSession for this instance.
ExecutionSession &getExecutionSession() { return *ES; }
- /// Returns a reference to the VSO representing the JIT'd main program.
- VSO &getMainVSO() { return Main; }
+ /// Returns a reference to the JITDylib representing the JIT'd main program.
+ JITDylib &getMainJITDylib() { return Main; }
/// Convenience method for defining an absolute symbol.
Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
- /// Adds an IR module to the given VSO.
- Error addIRModule(VSO &V, std::unique_ptr<Module> M);
+ /// Convenience method for defining an
- /// Adds an IR module to the Main VSO.
- Error addIRModule(std::unique_ptr<Module> M) {
- return addIRModule(Main, std::move(M));
+ /// Adds an IR module to the given JITDylib.
+ Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
+
+ /// Adds an IR module to the Main JITDylib.
+ Error addIRModule(ThreadSafeModule TSM) {
+ return addIRModule(Main, std::move(TSM));
}
- /// Look up a symbol in VSO V by the symbol's linker-mangled name (to look up
- /// symbols based on their IR name use the lookup function instead).
- Expected<JITEvaluatedSymbol> lookupLinkerMangled(VSO &V, StringRef Name);
+ /// Adds an object file to the given JITDylib.
+ Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
- /// Look up a symbol in the main VSO by the symbol's linker-mangled name (to
+ /// Adds an object file to the given JITDylib.
+ Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
+ return addObjectFile(Main, std::move(Obj));
+ }
+
+ /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
/// look up symbols based on their IR name use the lookup function instead).
+ Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
+ StringRef Name);
+
+ /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
+ /// (to look up symbols based on their IR name use the lookup function
+ /// instead).
Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
return lookupLinkerMangled(Main, Name);
}
- /// Look up a symbol in VSO V based on its IR symbol name.
- Expected<JITEvaluatedSymbol> lookup(VSO &V, StringRef UnmangledName) {
- return lookupLinkerMangled(V, mangle(UnmangledName));
+ /// Look up a symbol in JITDylib JD based on its IR symbol name.
+ Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) {
+ return lookupLinkerMangled(JD, mangle(UnmangledName));
}
- /// Look up a symbol in the main VSO based on its IR symbol name.
+ /// Look up a symbol in the main JITDylib based on its IR symbol name.
Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
return lookup(Main, UnmangledName);
}
@@ -77,11 +98,20 @@
/// Runs all not-yet-run static destructors.
Error runDestructors() { return DtorRunner.run(); }
+ /// Returns a reference to the ObjLinkingLayer
+ RTDyldObjectLinkingLayer2 &getObjLinkingLayer() { return ObjLinkingLayer; }
+
protected:
+
+ /// Create an LLJIT instance with a single compile thread.
LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
DataLayout DL);
- std::shared_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K);
+ /// Create an LLJIT instance with multiple compile threads.
+ LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
+ DataLayout DL, unsigned NumCompileThreads);
+
+ std::unique_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K);
std::string mangle(StringRef UnmangledName);
@@ -90,10 +120,10 @@
void recordCtorDtors(Module &M);
std::unique_ptr<ExecutionSession> ES;
- VSO &Main;
+ JITDylib &Main;
- std::unique_ptr<TargetMachine> TM;
DataLayout DL;
+ std::unique_ptr<ThreadPool> CompileThreads;
RTDyldObjectLinkingLayer2 ObjLinkingLayer;
IRCompileLayer2 CompileLayer;
@@ -105,10 +135,13 @@
/// compilation of LLVM IR.
class LLLazyJIT : public LLJIT {
public:
+
/// Create an LLLazyJIT instance.
+ /// If NumCompileThreads is not equal to zero, creates a multi-threaded
+ /// LLLazyJIT with the given number of compile threads.
static Expected<std::unique_ptr<LLLazyJIT>>
- Create(std::unique_ptr<ExecutionSession> ES,
- std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx);
+ Create(JITTargetMachineBuilder JTMB, DataLayout DL,
+ unsigned NumCompileThreads = 0);
/// Set an IR transform (e.g. pass manager pipeline) to run on each function
/// when it is compiled.
@@ -116,21 +149,35 @@
TransformLayer.setTransform(std::move(Transform));
}
- /// Add a module to be lazily compiled to VSO V.
- Error addLazyIRModule(VSO &V, std::unique_ptr<Module> M);
+ /// Sets the partition function.
+ void
+ setPartitionFunction(CompileOnDemandLayer2::PartitionFunction Partition) {
+ CODLayer.setPartitionFunction(std::move(Partition));
+ }
- /// Add a module to be lazily compiled to the main VSO.
- Error addLazyIRModule(std::unique_ptr<Module> M) {
+ /// Add a module to be lazily compiled to JITDylib JD.
+ Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
+
+ /// Add a module to be lazily compiled to the main JITDylib.
+ Error addLazyIRModule(ThreadSafeModule M) {
return addLazyIRModule(Main, std::move(M));
}
private:
+
+ // Create a single-threaded LLLazyJIT instance.
LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
- std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx,
- std::unique_ptr<JITCompileCallbackManager> CCMgr,
+ std::unique_ptr<TargetMachine> TM, DataLayout DL,
+ std::unique_ptr<LazyCallThroughManager> LCTMgr,
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
- std::unique_ptr<JITCompileCallbackManager> CCMgr;
+ // Create a multi-threaded LLLazyJIT instance.
+ LLLazyJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
+ DataLayout DL, unsigned NumCompileThreads,
+ std::unique_ptr<LazyCallThroughManager> LCTMgr,
+ std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
+
+ std::unique_ptr<LazyCallThroughManager> LCTMgr;
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
IRTransformLayer2 TransformLayer;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
index da37266..3bd23ae 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_LAYER_H
#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -30,14 +31,38 @@
/// Returns the ExecutionSession for this layer.
ExecutionSession &getExecutionSession() { return ES; }
- /// Adds a MaterializationUnit representing the given IR to the given VSO.
- virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M);
+ /// Sets the CloneToNewContextOnEmit flag (false by default).
+ ///
+ /// When set, IR modules added to this layer will be cloned on to a new
+ /// context before emit is called. This can be used by clients who want
+ /// to load all IR using one LLVMContext (to save memory via type and
+ /// constant uniquing), but want to move Modules to fresh contexts before
+ /// compiling them to enable concurrent compilation.
+ /// Single threaded clients, or clients who load every module on a new
+ /// context, need not set this.
+ void setCloneToNewContextOnEmit(bool CloneToNewContextOnEmit) {
+ this->CloneToNewContextOnEmit = CloneToNewContextOnEmit;
+ }
+
+ /// Returns the current value of the CloneToNewContextOnEmit flag.
+ bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
+
+ /// Adds a MaterializationUnit representing the given IR to the given
+ /// JITDylib.
+ virtual Error add(JITDylib &JD, VModuleKey K, ThreadSafeModule TSM);
+
+ /// Adds a MaterializationUnit representing the given IR to the main
+ /// JITDylib.
+ Error add(VModuleKey K, ThreadSafeModule TSM) {
+ return add(ES.getMainJITDylib(), K, std::move(TSM));
+ }
/// Emit should materialize the given IR.
virtual void emit(MaterializationResponsibility R, VModuleKey K,
- std::unique_ptr<Module> M) = 0;
+ ThreadSafeModule TSM) = 0;
private:
+ bool CloneToNewContextOnEmit = false;
ExecutionSession &ES;
};
@@ -51,22 +76,27 @@
/// Create an IRMaterializationLayer. Scans the module to build the
/// SymbolFlags and SymbolToDefinition maps.
- IRMaterializationUnit(ExecutionSession &ES, std::unique_ptr<Module> M);
+ IRMaterializationUnit(ExecutionSession &ES, ThreadSafeModule TSM);
/// Create an IRMaterializationLayer from a module, and pre-existing
/// SymbolFlags and SymbolToDefinition maps. The maps must provide
/// entries for each definition in M.
/// This constructor is useful for delegating work from one
/// IRMaterializationUnit to another.
- IRMaterializationUnit(std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
+ IRMaterializationUnit(ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
SymbolNameToDefinitionMap SymbolToDefinition);
+ /// Return the ModuleIdentifier as the name for this MaterializationUnit.
+ StringRef getName() const override;
+
+ const ThreadSafeModule &getModule() const { return TSM; }
+
protected:
- std::unique_ptr<Module> M;
+ ThreadSafeModule TSM;
SymbolNameToDefinitionMap SymbolToDefinition;
private:
- void discard(const VSO &V, SymbolStringPtr Name) override;
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
};
/// MaterializationUnit that materializes modules by calling the 'emit' method
@@ -74,7 +104,8 @@
class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
public:
BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K,
- std::unique_ptr<Module> M);
+ ThreadSafeModule TSM);
+
private:
void materialize(MaterializationResponsibility R) override;
@@ -92,8 +123,15 @@
/// Returns the execution session for this layer.
ExecutionSession &getExecutionSession() { return ES; }
- /// Adds a MaterializationUnit representing the given IR to the given VSO.
- virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+ /// Adds a MaterializationUnit representing the given IR to the given
+ /// JITDylib.
+ virtual Error add(JITDylib &JD, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+
+ /// Adds a MaterializationUnit representing the given object to the main
+ /// JITDylib.
+ Error add(VModuleKey K, std::unique_ptr<MemoryBuffer> O) {
+ return add(ES.getMainJITDylib(), K, std::move(O));
+ }
/// Emit should materialize the given IR.
virtual void emit(MaterializationResponsibility R, VModuleKey K,
@@ -114,10 +152,13 @@
std::unique_ptr<MemoryBuffer> O,
SymbolFlagsMap SymbolFlags);
+ /// Return the buffer's identifier as the name for this MaterializationUnit.
+ StringRef getName() const override;
+
private:
void materialize(MaterializationResponsibility R) override;
- void discard(const VSO &V, SymbolStringPtr Name) override;
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
ObjectLayer &L;
VModuleKey K;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h
new file mode 100644
index 0000000..8f89700
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h
@@ -0,0 +1,193 @@
+//===------ LazyReexports.h -- Utilities for lazy reexports -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Lazy re-exports are similar to normal re-exports, except that for callable
+// symbols the definitions are replaced with trampolines that will look up and
+// call through to the re-exported symbol at runtime. This can be used to
+// enable lazy compilation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
+#define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
+
+namespace llvm {
+
+class Triple;
+
+namespace orc {
+
+/// Manages a set of 'lazy call-through' trampolines. These are compiler
+/// re-entry trampolines that are pre-bound to look up a given symbol in a given
+/// JITDylib, then jump to that address. Since compilation of symbols is
+/// triggered on first lookup, these call-through trampolines can be used to
+/// implement lazy compilation.
+///
+/// The easiest way to construct these call-throughs is using the lazyReexport
+/// function.
+class LazyCallThroughManager {
+public:
+ /// Clients will want to take some action on first resolution, e.g. updating
+ /// a stub pointer. Instances of this class can be used to implement this.
+ class NotifyResolvedFunction {
+ public:
+ virtual ~NotifyResolvedFunction() {}
+
+ /// Called the first time a lazy call through is executed and the target
+ /// symbol resolved.
+ virtual Error operator()(JITDylib &SourceJD,
+ const SymbolStringPtr &SymbolName,
+ JITTargetAddress ResolvedAddr) = 0;
+
+ private:
+ virtual void anchor();
+ };
+
+ template <typename NotifyResolvedImpl>
+ class NotifyResolvedFunctionImpl : public NotifyResolvedFunction {
+ public:
+ NotifyResolvedFunctionImpl(NotifyResolvedImpl NotifyResolved)
+ : NotifyResolved(std::move(NotifyResolved)) {}
+ Error operator()(JITDylib &SourceJD, const SymbolStringPtr &SymbolName,
+ JITTargetAddress ResolvedAddr) {
+ return NotifyResolved(SourceJD, SymbolName, ResolvedAddr);
+ }
+
+ private:
+ NotifyResolvedImpl NotifyResolved;
+ };
+
+ /// Create a shared NotifyResolvedFunction from a given type that is
+ /// callable with the correct signature.
+ template <typename NotifyResolvedImpl>
+ static std::unique_ptr<NotifyResolvedFunction>
+ createNotifyResolvedFunction(NotifyResolvedImpl NotifyResolved) {
+ return llvm::make_unique<NotifyResolvedFunctionImpl<NotifyResolvedImpl>>(
+ std::move(NotifyResolved));
+ }
+
+ // Return a free call-through trampoline and bind it to look up and call
+ // through to the given symbol.
+ Expected<JITTargetAddress> getCallThroughTrampoline(
+ JITDylib &SourceJD, SymbolStringPtr SymbolName,
+ std::shared_ptr<NotifyResolvedFunction> NotifyResolved);
+
+protected:
+ LazyCallThroughManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddr,
+ std::unique_ptr<TrampolinePool> TP);
+
+ JITTargetAddress callThroughToSymbol(JITTargetAddress TrampolineAddr);
+
+ void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
+ this->TP = std::move(TP);
+ }
+
+private:
+ using ReexportsMap =
+ std::map<JITTargetAddress, std::pair<JITDylib *, SymbolStringPtr>>;
+
+ using NotifiersMap =
+ std::map<JITTargetAddress, std::shared_ptr<NotifyResolvedFunction>>;
+
+ std::mutex LCTMMutex;
+ ExecutionSession &ES;
+ JITTargetAddress ErrorHandlerAddr;
+ std::unique_ptr<TrampolinePool> TP;
+ ReexportsMap Reexports;
+ NotifiersMap Notifiers;
+};
+
+/// A lazy call-through manager that builds trampolines in the current process.
+class LocalLazyCallThroughManager : public LazyCallThroughManager {
+private:
+ LocalLazyCallThroughManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddr)
+ : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
+
+ template <typename ORCABI> Error init() {
+ auto TP = LocalTrampolinePool<ORCABI>::Create(
+ [this](JITTargetAddress TrampolineAddr) {
+ return callThroughToSymbol(TrampolineAddr);
+ });
+
+ if (!TP)
+ return TP.takeError();
+
+ setTrampolinePool(std::move(*TP));
+ return Error::success();
+ }
+
+public:
+ /// Create a LocalLazyCallThroughManager using the given ABI. See
+ /// createLocalLazyCallThroughManager.
+ template <typename ORCABI>
+ static Expected<std::unique_ptr<LocalLazyCallThroughManager>>
+ Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
+ auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
+ new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
+
+ if (auto Err = LLCTM->init<ORCABI>())
+ return std::move(Err);
+
+ return std::move(LLCTM);
+ }
+};
+
+/// Create a LocalLazyCallThroughManager from the given triple and execution
+/// session.
+Expected<std::unique_ptr<LazyCallThroughManager>>
+createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddr);
+
+/// A materialization unit that builds lazy re-exports. These are callable
+/// entry points that call through to the given symbols.
+/// Unlike a 'true' re-export, the address of the lazy re-export will not
+/// match the address of the re-exported symbol, but calling it will behave
+/// the same as calling the re-exported symbol.
+class LazyReexportsMaterializationUnit : public MaterializationUnit {
+public:
+ LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager,
+ IndirectStubsManager &ISManager,
+ JITDylib &SourceJD,
+ SymbolAliasMap CallableAliases);
+
+ StringRef getName() const override;
+
+private:
+ void materialize(MaterializationResponsibility R) override;
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
+ static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
+
+ LazyCallThroughManager &LCTManager;
+ IndirectStubsManager &ISManager;
+ JITDylib &SourceJD;
+ SymbolAliasMap CallableAliases;
+ std::shared_ptr<LazyCallThroughManager::NotifyResolvedFunction>
+ NotifyResolved;
+};
+
+/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
+/// is a callable symbol that will look up and dispatch to the given aliasee on
+/// first call. All subsequent calls will go directly to the aliasee.
+inline std::unique_ptr<LazyReexportsMaterializationUnit>
+lazyReexports(LazyCallThroughManager &LCTManager,
+ IndirectStubsManager &ISManager, JITDylib &SourceJD,
+ SymbolAliasMap CallableAliases) {
+ return llvm::make_unique<LazyReexportsMaterializationUnit>(
+ LCTManager, ISManager, SourceJD, std::move(CallableAliases));
+}
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
index 52c8c16..4c6162a 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
@@ -31,12 +31,12 @@
public:
virtual ~SymbolResolver() = default;
- /// Returns the flags for each symbol in Symbols that can be found,
- /// along with the set of symbol that could not be found.
- virtual SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) = 0;
+ /// Returns the subset of the given symbols that the caller is responsible for
+ /// materializing.
+ virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
/// For each symbol in Symbols that can be found, assigns that symbols
- /// value in Query. Returns the set of symbols that could not be found.
+ /// value in Query. Returns the set of symbols that could not be found.
virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) = 0;
@@ -46,16 +46,18 @@
/// Implements SymbolResolver with a pair of supplied function objects
/// for convenience. See createSymbolResolver.
-template <typename LookupFlagsFn, typename LookupFn>
+template <typename GetResponsibilitySetFn, typename LookupFn>
class LambdaSymbolResolver final : public SymbolResolver {
public:
- template <typename LookupFlagsFnRef, typename LookupFnRef>
- LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
- : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
+ template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
+ LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
+ LookupFnRef &&Lookup)
+ : GetResponsibilitySet(
+ std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
Lookup(std::forward<LookupFnRef>(Lookup)) {}
- SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
- return LookupFlags(Symbols);
+ SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
+ return GetResponsibilitySet(Symbols);
}
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
@@ -64,34 +66,37 @@
}
private:
- LookupFlagsFn LookupFlags;
+ GetResponsibilitySetFn GetResponsibilitySet;
LookupFn Lookup;
};
/// Creates a SymbolResolver implementation from the pair of supplied
/// function objects.
-template <typename LookupFlagsFn, typename LookupFn>
+template <typename GetResponsibilitySetFn, typename LookupFn>
std::unique_ptr<LambdaSymbolResolver<
typename std::remove_cv<
- typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
typename std::remove_cv<
typename std::remove_reference<LookupFn>::type>::type>>
-createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
+createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
+ LookupFn &&Lookup) {
using LambdaSymbolResolverImpl = LambdaSymbolResolver<
typename std::remove_cv<
- typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
typename std::remove_cv<
typename std::remove_reference<LookupFn>::type>::type>;
return llvm::make_unique<LambdaSymbolResolverImpl>(
- std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
+ std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
+ std::forward<LookupFn>(Lookup));
}
+/// Legacy adapter. Remove once we kill off the old ORC layers.
class JITSymbolResolverAdapter : public JITSymbolResolver {
public:
JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
MaterializationResponsibility *MR);
- Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
- Expected<LookupResult> lookup(const LookupSet &Symbols) override;
+ Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
+ void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
private:
ExecutionSession &ES;
@@ -100,27 +105,29 @@
MaterializationResponsibility *MR;
};
-/// Use the given legacy-style FindSymbol function (i.e. a function that
-/// takes a const std::string& or StringRef and returns a JITSymbol) to
-/// find the flags for each symbol in Symbols and store their flags in
-/// SymbolFlags. If any JITSymbol returned by FindSymbol is in an error
-/// state the function returns immediately with that error, otherwise it
-/// returns the set of symbols not found.
+/// Use the given legacy-style FindSymbol function (i.e. a function that takes
+/// a const std::string& or StringRef and returns a JITSymbol) to get the
+/// subset of symbols that the caller is responsible for materializing. If any
+/// JITSymbol returned by FindSymbol is in an error state the function returns
+/// immediately with that error.
///
-/// Useful for implementing lookupFlags bodies that query legacy resolvers.
+/// Useful for implementing getResponsibilitySet bodies that query legacy
+/// resolvers.
template <typename FindSymbolFn>
-Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols,
- FindSymbolFn FindSymbol) {
- SymbolFlagsMap SymbolFlags;
+Expected<SymbolNameSet>
+getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
+ FindSymbolFn FindSymbol) {
+ SymbolNameSet Result;
for (auto &S : Symbols) {
- if (JITSymbol Sym = FindSymbol(*S))
- SymbolFlags[S] = Sym.getFlags();
- else if (auto Err = Sym.takeError())
+ if (JITSymbol Sym = FindSymbol(*S)) {
+ if (!Sym.getFlags().isStrong())
+ Result.insert(S);
+ } else if (auto Err = Sym.takeError())
return std::move(Err);
}
- return SymbolFlags;
+ return Result;
}
/// Use the given legacy-style FindSymbol function (i.e. a function that
@@ -177,12 +184,13 @@
: ES(ES), LegacyLookup(std::move(LegacyLookup)),
ReportError(std::move(ReportError)) {}
- SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
- if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup))
- return std::move(*SymbolFlags);
+ SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
+ if (auto ResponsibilitySet =
+ getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
+ return std::move(*ResponsibilitySet);
else {
- ReportError(SymbolFlags.takeError());
- return SymbolFlagsMap();
+ ReportError(ResponsibilitySet.takeError());
+ return SymbolNameSet();
}
}
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
index 3dd3cfe..03fefb6 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
@@ -23,10 +23,10 @@
class NullResolver : public SymbolResolver {
public:
- SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) override;
+ SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final;
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) override;
+ SymbolNameSet Symbols) final;
};
/// SymbolResolver impliementation that rejects all resolution requests.
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
index 581c598..49e7b53 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
@@ -238,7 +238,78 @@
unsigned MinStubs, void *InitialPtrVal);
};
-} // end namespace orc
-} // end namespace llvm
+// @brief Mips32 support.
+//
+// Mips32 supports lazy JITing.
+class OrcMips32_Base {
+public:
+ static const unsigned PointerSize = 4;
+ static const unsigned TrampolineSize = 20;
+ static const unsigned ResolverCodeSize = 0xfc;
+ using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
+ using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
+ void *TrampolineId);
+ /// @brief Write the requsted number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
+
+ /// @brief Write the resolver code into the given memory. The user is be
+ /// responsible for allocating the memory and setting permissions.
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian);
+ /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// the nearest page size.
+ ///
+ /// E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k
+ /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
+ /// will return a block of 1024 (2-pages worth).
+ static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
+};
+
+
+class OrcMips32Le : public OrcMips32_Base {
+public:
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
+ { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
+};
+
+class OrcMips32Be : public OrcMips32_Base {
+public:
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
+ { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
+};
+
+// @brief Mips64 support.
+//
+// Mips64 supports lazy JITing.
+class OrcMips64 {
+public:
+ static const unsigned PointerSize = 8;
+ static const unsigned TrampolineSize = 40;
+ static const unsigned ResolverCodeSize = 0x11C;
+
+ using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
+ using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
+ void *TrampolineId);
+ /// @brief Write the resolver code into the given memory. The user is be
+ /// responsible for allocating the memory and setting permissions.
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr);
+
+ /// @brief Write the requsted number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
+
+ /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+ /// the nearest page size.
+ ///
+ /// E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k
+ /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
+ /// will return a block of 1024 (2-pages worth).
+ static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
+};
+
+ } // end namespace orc
+ } // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 739e5ba..99468e2 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -70,8 +70,7 @@
RemoteRTDyldMemoryManager &
operator=(const RemoteRTDyldMemoryManager &) = delete;
RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
- RemoteRTDyldMemoryManager &
- operator=(RemoteRTDyldMemoryManager &&) = default;
+ RemoteRTDyldMemoryManager &operator=(RemoteRTDyldMemoryManager &&) = delete;
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
@@ -447,16 +446,24 @@
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
};
- /// Remote compile callback manager.
- class RemoteCompileCallbackManager : public JITCompileCallbackManager {
+ class RemoteTrampolinePool : public TrampolinePool {
public:
- RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
- ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
+ RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {}
+
+ Expected<JITTargetAddress> getTrampoline() override {
+ std::lock_guard<std::mutex> Lock(RTPMutex);
+ if (AvailableTrampolines.empty()) {
+ if (auto Err = grow())
+ return std::move(Err);
+ }
+ assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
+ auto TrampolineAddr = AvailableTrampolines.back();
+ AvailableTrampolines.pop_back();
+ return TrampolineAddr;
+ }
private:
- Error grow() override {
+ Error grow() {
JITTargetAddress BlockAddr = 0;
uint32_t NumTrampolines = 0;
if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
@@ -471,7 +478,20 @@
return Error::success();
}
+ std::mutex RTPMutex;
OrcRemoteTargetClient &Client;
+ std::vector<JITTargetAddress> AvailableTrampolines;
+ };
+
+ /// Remote compile callback manager.
+ class RemoteCompileCallbackManager : public JITCompileCallbackManager {
+ public:
+ RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
+ ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : JITCompileCallbackManager(
+ llvm::make_unique<RemoteTrampolinePool>(Client), ES,
+ ErrorHandlerAddress) {}
};
/// Create an OrcRemoteTargetClient.
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
index bc0da0f..8db9e31 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
@@ -87,8 +87,7 @@
public:
static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) {
- return serializeSeq(C, static_cast<JITSymbolFlags::UnderlyingType>(Flags),
- Flags.getTargetFlags());
+ return serializeSeq(C, Flags.getRawFlagsValue(), Flags.getTargetFlags());
}
static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) {
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index 47bd90b..953b73e 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -25,6 +25,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
#include <future>
@@ -207,73 +208,6 @@
namespace detail {
-// FIXME: Remove MSVCPError/MSVCPExpected once MSVC's future implementation
-// supports classes without default constructors.
-#ifdef _MSC_VER
-
-namespace msvc_hacks {
-
-// Work around MSVC's future implementation's use of default constructors:
-// A default constructed value in the promise will be overwritten when the
-// real error is set - so the default constructed Error has to be checked
-// already.
-class MSVCPError : public Error {
-public:
- MSVCPError() { (void)!!*this; }
-
- MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {}
-
- MSVCPError &operator=(MSVCPError Other) {
- Error::operator=(std::move(Other));
- return *this;
- }
-
- MSVCPError(Error Err) : Error(std::move(Err)) {}
-};
-
-// Work around MSVC's future implementation, similar to MSVCPError.
-template <typename T> class MSVCPExpected : public Expected<T> {
-public:
- MSVCPExpected()
- : Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) {
- consumeError(this->takeError());
- }
-
- MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {}
-
- MSVCPExpected &operator=(MSVCPExpected &&Other) {
- Expected<T>::operator=(std::move(Other));
- return *this;
- }
-
- MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {}
-
- template <typename OtherT>
- MSVCPExpected(
- OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
- : Expected<T>(std::move(Val)) {}
-
- template <class OtherT>
- MSVCPExpected(
- Expected<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
- : Expected<T>(std::move(Other)) {}
-
- template <class OtherT>
- explicit MSVCPExpected(
- Expected<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
- : Expected<T>(std::move(Other)) {}
-};
-
-} // end namespace msvc_hacks
-
-#endif // _MSC_VER
-
/// Provides a typedef for a tuple containing the decayed argument types.
template <typename T> class FunctionArgsTuple;
@@ -293,10 +227,10 @@
#ifdef _MSC_VER
// The ErrorReturnType wrapped in a std::promise.
- using ReturnPromiseType = std::promise<msvc_hacks::MSVCPExpected<RetT>>;
+ using ReturnPromiseType = std::promise<MSVCPExpected<RetT>>;
// The ErrorReturnType wrapped in a std::future.
- using ReturnFutureType = std::future<msvc_hacks::MSVCPExpected<RetT>>;
+ using ReturnFutureType = std::future<MSVCPExpected<RetT>>;
#else
// The ErrorReturnType wrapped in a std::promise.
using ReturnPromiseType = std::promise<ErrorReturnType>;
@@ -325,10 +259,10 @@
#ifdef _MSC_VER
// The ErrorReturnType wrapped in a std::promise.
- using ReturnPromiseType = std::promise<msvc_hacks::MSVCPError>;
+ using ReturnPromiseType = std::promise<MSVCPError>;
// The ErrorReturnType wrapped in a std::future.
- using ReturnFutureType = std::future<msvc_hacks::MSVCPError>;
+ using ReturnFutureType = std::future<MSVCPError>;
#else
// The ErrorReturnType wrapped in a std::promise.
using ReturnPromiseType = std::promise<ErrorReturnType>;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 6510976..0c30520 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -44,44 +44,80 @@
const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving finalization notifications.
- using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
+ using NotifyEmittedFunction = std::function<void(VModuleKey)>;
using GetMemoryManagerFunction =
- std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
+ std::function<std::unique_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
/// Construct an ObjectLinkingLayer with the given NotifyLoaded,
- /// and NotifyFinalized functors.
+ /// and NotifyEmitted functors.
RTDyldObjectLinkingLayer2(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
- NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
+ NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction());
/// Emit the object.
void emit(MaterializationResponsibility R, VModuleKey K,
std::unique_ptr<MemoryBuffer> O) override;
- /// Map section addresses for the object associated with the
- /// VModuleKey K.
- void mapSectionAddress(VModuleKey K, const void *LocalAddress,
- JITTargetAddress TargetAddr) const;
-
/// Set the 'ProcessAllSections' flag.
///
/// If set to true, all sections in each object file will be allocated using
/// the memory manager, rather than just the sections required for execution.
///
/// This is kludgy, and may be removed in the future.
- void setProcessAllSections(bool ProcessAllSections) {
+ RTDyldObjectLinkingLayer2 &setProcessAllSections(bool ProcessAllSections) {
this->ProcessAllSections = ProcessAllSections;
+ return *this;
+ }
+
+ /// Instructs this RTDyldLinkingLayer2 instance to override the symbol flags
+ /// returned by RuntimeDyld for any given object file with the flags supplied
+ /// by the MaterializationResponsibility instance. This is a workaround to
+ /// support symbol visibility in COFF, which does not use the libObject's
+ /// SF_Exported flag. Use only when generating / adding COFF object files.
+ ///
+ /// FIXME: We should be able to remove this if/when COFF properly tracks
+ /// exported symbols.
+ RTDyldObjectLinkingLayer2 &
+ setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
+ this->OverrideObjectFlags = OverrideObjectFlags;
+ return *this;
+ }
+
+ /// If set, this RTDyldObjectLinkingLayer2 instance will claim responsibility
+ /// for any symbols provided by a given object file that were not already in
+ /// the MaterializationResponsibility instance. Setting this flag allows
+ /// higher-level program representations (e.g. LLVM IR) to be added based on
+ /// only a subset of the symbols they provide, without having to write
+ /// intervening layers to scan and add the additional symbols. This trades
+ /// diagnostic quality for convenience however: If all symbols are enumerated
+ /// up-front then clashes can be detected and reported early (and usually
+ /// deterministically). If this option is set, clashes for the additional
+ /// symbols may not be detected until late, and detection may depend on
+ /// the flow of control through JIT'd code. Use with care.
+ RTDyldObjectLinkingLayer2 &
+ setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
+ this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
+ return *this;
}
private:
+ Error onObjLoad(VModuleKey K, MaterializationResponsibility &R,
+ object::ObjectFile &Obj,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
+ std::map<StringRef, JITEvaluatedSymbol> Resolved,
+ std::set<StringRef> &InternalSymbols);
+
+ void onObjEmit(VModuleKey K, MaterializationResponsibility &R, Error Err);
+
mutable std::mutex RTDyldLayerMutex;
GetMemoryManagerFunction GetMemoryManager;
NotifyLoadedFunction NotifyLoaded;
- NotifyFinalizedFunction NotifyFinalized;
- bool ProcessAllSections;
- std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
+ NotifyEmittedFunction NotifyEmitted;
+ bool ProcessAllSections = false;
+ bool OverrideObjectFlags = false;
+ bool AutoClaimObjectSymbols = false;
std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
};
@@ -175,7 +211,7 @@
}
~ConcreteLinkedObject() override {
- if (this->Parent.NotifyFreed)
+ if (this->Parent.NotifyFreed && ObjForNotify.getBinary())
this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
MemMgr->deregisterEHFrames();
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
new file mode 100644
index 0000000..bf946de
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
@@ -0,0 +1,163 @@
+//===----------- ThreadSafeModule.h -- Layer interfaces ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Thread safe wrappers and utilities for Module and LLVMContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H
+#define LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H
+
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Compiler.h"
+
+#include <functional>
+#include <memory>
+#include <mutex>
+
+namespace llvm {
+namespace orc {
+
+/// An LLVMContext together with an associated mutex that can be used to lock
+/// the context to prevent concurrent access by other threads.
+class ThreadSafeContext {
+private:
+ struct State {
+ State(std::unique_ptr<LLVMContext> Ctx) : Ctx(std::move(Ctx)) {}
+
+ std::unique_ptr<LLVMContext> Ctx;
+ std::recursive_mutex Mutex;
+ };
+
+public:
+ // RAII based lock for ThreadSafeContext.
+ class LLVM_NODISCARD Lock {
+ private:
+ using UnderlyingLock = std::lock_guard<std::recursive_mutex>;
+
+ public:
+ Lock(std::shared_ptr<State> S)
+ : S(std::move(S)),
+ L(llvm::make_unique<UnderlyingLock>(this->S->Mutex)) {}
+
+ private:
+ std::shared_ptr<State> S;
+ std::unique_ptr<UnderlyingLock> L;
+ };
+
+ /// Construct a null context.
+ ThreadSafeContext() = default;
+
+ /// Construct a ThreadSafeContext from the given LLVMContext.
+ ThreadSafeContext(std::unique_ptr<LLVMContext> NewCtx)
+ : S(std::make_shared<State>(std::move(NewCtx))) {
+ assert(S->Ctx != nullptr &&
+ "Can not construct a ThreadSafeContext from a nullptr");
+ }
+
+ /// Returns a pointer to the LLVMContext that was used to construct this
+ /// instance, or null if the instance was default constructed.
+ LLVMContext *getContext() { return S ? S->Ctx.get() : nullptr; }
+
+ /// Returns a pointer to the LLVMContext that was used to construct this
+ /// instance, or null if the instance was default constructed.
+ const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; }
+
+ Lock getLock() {
+ assert(S && "Can not lock an empty ThreadSafeContext");
+ return Lock(S);
+ }
+
+private:
+ std::shared_ptr<State> S;
+};
+
+/// An LLVM Module together with a shared ThreadSafeContext.
+class ThreadSafeModule {
+public:
+ /// Default construct a ThreadSafeModule. This results in a null module and
+ /// null context.
+ ThreadSafeModule() = default;
+
+ ThreadSafeModule(ThreadSafeModule &&Other) = default;
+
+ ThreadSafeModule &operator=(ThreadSafeModule &&Other) {
+ // We have to explicitly define this move operator to copy the fields in
+ // reverse order (i.e. module first) to ensure the dependencies are
+ // protected: The old module that is being overwritten must be destroyed
+ // *before* the context that it depends on.
+ // We also need to lock the context to make sure the module tear-down
+ // does not overlap any other work on the context.
+ if (M) {
+ auto L = getContextLock();
+ M = nullptr;
+ }
+ M = std::move(Other.M);
+ TSCtx = std::move(Other.TSCtx);
+ return *this;
+ }
+
+ /// Construct a ThreadSafeModule from a unique_ptr<Module> and a
+ /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the
+ /// given context.
+ ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
+ : M(std::move(M)), TSCtx(std::move(Ctx)) {}
+
+ /// Construct a ThreadSafeModule from a unique_ptr<Module> and an
+ /// existing ThreadSafeContext.
+ ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
+ : M(std::move(M)), TSCtx(std::move(TSCtx)) {}
+
+ ~ThreadSafeModule() {
+ // We need to lock the context while we destruct the module.
+ if (M) {
+ auto L = getContextLock();
+ M = nullptr;
+ }
+ }
+
+ /// Get the module wrapped by this ThreadSafeModule.
+ Module *getModule() { return M.get(); }
+
+ /// Get the module wrapped by this ThreadSafeModule.
+ const Module *getModule() const { return M.get(); }
+
+ /// Take out a lock on the ThreadSafeContext for this module.
+ ThreadSafeContext::Lock getContextLock() { return TSCtx.getLock(); }
+
+ /// Boolean conversion: This ThreadSafeModule will evaluate to true if it
+ /// wraps a non-null module.
+ explicit operator bool() {
+ if (M) {
+ assert(TSCtx.getContext() &&
+ "Non-null module must have non-null context");
+ return true;
+ }
+ return false;
+ }
+
+private:
+ std::unique_ptr<Module> M;
+ ThreadSafeContext TSCtx;
+};
+
+using GVPredicate = std::function<bool(const GlobalValue &)>;
+using GVModifier = std::function<void(GlobalValue &)>;
+
+/// Clones the given module on to a new context.
+ThreadSafeModule
+cloneToNewContext(ThreadSafeModule &TSMW,
+ GVPredicate ShouldCloneDef = GVPredicate(),
+ GVModifier UpdateClonedDefSource = GVModifier());
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H