blob: 11d7c091947e8a806a7a73350f7cf68f11a0a0ba [file] [log] [blame]
//===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Contains core ORC APIs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
#define LLVM_EXECUTIONENGINE_ORC_CORE_H
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/IR/Module.h"
#include <list>
#include <map>
#include <memory>
#include <set>
#include <vector>
namespace llvm {
namespace orc {
// Forward declare some classes.
class AsynchronousSymbolQuery;
class ExecutionSession;
class MaterializationUnit;
class MaterializationResponsibility;
class VSO;
/// VModuleKey provides a unique identifier (allocated and managed by
/// ExecutionSessions) for a module added to the JIT.
using VModuleKey = uint64_t;
/// A set of symbol names (represented by SymbolStringPtrs for
// 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>;
/// Render a SymbolDependendeMap.
raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
/// A list of VSO pointers.
using VSOList = std::vector<VSO *>;
/// Render a VSOList.
raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs);
/// Callback to notify client that symbols have been resolved.
using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
/// Callback to notify client that symbols are ready for execution.
using SymbolsReadyCallback = std::function<void(Error)>;
/// Callback to register the dependencies for a given query.
using RegisterDependenciesFunction =
std::function<void(const SymbolDependenceMap &)>;
/// This can be used as the value for a RegisterDependenciesFunction if there
/// are no dependants to register with.
extern RegisterDependenciesFunction NoDependenciesToRegister;
/// Used to notify a VSO that the given set of symbols failed to materialize.
class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
public:
static char ID;
FailedToMaterialize(SymbolNameSet Symbols);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
const SymbolNameSet &getSymbols() const { return Symbols; }
private:
SymbolNameSet Symbols;
};
/// Used to notify clients when symbols can not be found during a lookup.
class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
public:
static char ID;
SymbolsNotFound(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.
///
/// 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
/// symbols of an error.
class MaterializationResponsibility {
friend class MaterializationUnit;
public:
MaterializationResponsibility(MaterializationResponsibility &&) = default;
MaterializationResponsibility &
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.
~MaterializationResponsibility();
/// Returns the target VSO that these symbols are being materialized
/// into.
VSO &getTargetVSO() const { return V; }
/// Returns the symbol flags map for this responsibility instance.
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();
/// 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.
void resolve(const SymbolMap &Symbols);
/// Finalizes all symbols tracked by this instance.
void finalize();
/// Adds new symbols to the VSO and this responsibility instance.
/// VSO 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.
/// This will remove all symbols covered by this MaterializationResponsibilty
/// from V, and send an error to any queries waiting on these symbols.
void failMaterialization();
/// Transfers responsibility to the given MaterializationUnit for all
/// symbols defined by that MaterializationUnit. This allows
/// materializers to break up work based on run-time information (e.g.
/// by introspecting which symbols have actually been looked up and
/// materializing only those).
void replace(std::unique_ptr<MaterializationUnit> MU);
/// Delegates responsibility for the given symbols to the returned
/// materialization responsibility. Useful for breaking up work between
/// threads, or different kinds of materialization processes.
MaterializationResponsibility delegate(const SymbolNameSet &Symbols);
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependencies);
/// Add dependencies that apply to all symbols covered by this instance.
void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
private:
/// Create a MaterializationResponsibility for the given VSO and
/// initial symbols.
MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
VSO &V;
SymbolFlagsMap SymbolFlags;
};
/// A MaterializationUnit represents a set of symbol definitions that can
/// be materialized as a group, or individually discarded (when
/// 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.
class MaterializationUnit {
public:
MaterializationUnit(SymbolFlagsMap InitalSymbolFlags)
: SymbolFlags(std::move(InitalSymbolFlags)) {}
virtual ~MaterializationUnit() {}
/// 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)));
}
/// Called by VSOs to notify MaterializationUnits that the given symbol has
/// been overridden.
void doDiscard(const VSO &V, SymbolStringPtr Name) {
SymbolFlags.erase(Name);
discard(V, std::move(Name));
}
protected:
SymbolFlagsMap SymbolFlags;
private:
virtual void anchor();
/// Implementations of this method should materialize all symbols
/// in the materialzation unit, except for those that have been
/// previously discarded.
virtual void materialize(MaterializationResponsibility R) = 0;
/// Implementations of this method should discard the given symbol
/// 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;
};
using MaterializationUnitList =
std::vector<std::unique_ptr<MaterializationUnit>>;
/// A MaterializationUnit implementation for pre-existing absolute symbols.
///
/// All symbols will be resolved and marked ready as soon as the unit is
/// materialized.
class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
public:
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
private:
void materialize(MaterializationResponsibility R) override;
void discard(const VSO &V, 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.:
/// \code{.cpp}
/// VSO &V = ...;
/// SymbolStringPtr Foo = ...;
/// JITEvaluatedSymbol FooSym = ...;
/// if (auto Err = V.define(absoluteSymbols({{Foo, FooSym}})))
/// return Err;
/// \endcode
///
inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
absoluteSymbols(SymbolMap Symbols) {
return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
std::move(Symbols));
}
struct SymbolAliasMapEntry {
SymbolAliasMapEntry() = default;
SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
: Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
SymbolStringPtr Aliasee;
JITSymbolFlags AliasFlags;
};
/// A map of Symbols to (Symbol, Flags) pairs.
using SymbolAliasMap = std::map<SymbolStringPtr, SymbolAliasMapEntry>;
/// A materialization unit for symbol aliases. Allows existing symbols to be
/// 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.
///
/// 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);
private:
void materialize(MaterializationResponsibility R) override;
void discard(const VSO &V, SymbolStringPtr Name) override;
static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
VSO *SourceVSO = 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}
/// SymbolStringPtr Baz = ...;
/// SymbolStringPtr Qux = ...;
/// if (auto Err = V.define(symbolAliases({
/// {Baz, { Foo, JITSymbolFlags::Exported }},
/// {Qux, { Bar, JITSymbolFlags::Weak }}}))
/// return Err;
/// \endcode
inline std::unique_ptr<ReExportsMaterializationUnit>
symbolAliases(SymbolAliasMap Aliases) {
return llvm::make_unique<ReExportsMaterializationUnit>(nullptr,
std::move(Aliases));
}
/// Create a materialization unit for re-exporting symbols from another VSO
/// with alternative names/flags.
inline std::unique_ptr<ReExportsMaterializationUnit>
reexports(VSO &SourceV, SymbolAliasMap Aliases) {
return llvm::make_unique<ReExportsMaterializationUnit>(&SourceV,
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.
Expected<SymbolAliasMap>
buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols);
/// 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;
public:
/// Create a query for the given symbols, notify-resolved and
/// notify-ready callbacks.
AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
SymbolsResolvedCallback NotifySymbolsResolved,
SymbolsReadyCallback NotifySymbolsReady);
/// Set the resolved symbol information for the given symbol name.
void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
/// Returns true if all symbols covered by this query have been
/// resolved.
bool isFullyResolved() const { return NotYetResolvedCount == 0; }
/// Call the NotifySymbolsResolved callback.
///
/// This should only be called if all symbols covered by the query have been
/// resolved.
void handleFullyResolved();
/// Notify the query that a requested symbol is ready for execution.
void notifySymbolReady();
/// Returns true if all symbols covered by this query are ready.
bool isFullyReady() const { return NotYetReadyCount == 0; }
/// Calls the NotifySymbolsReady callback.
///
/// This should only be called if all symbols covered by this query are ready.
void handleFullyReady();
private:
void addQueryDependence(VSO &V, SymbolStringPtr Name);
void removeQueryDependence(VSO &V, const SymbolStringPtr &Name);
bool canStillFail();
void handleFailed(Error Err);
void detach();
SymbolsResolvedCallback NotifySymbolsResolved;
SymbolsReadyCallback NotifySymbolsReady;
SymbolDependenceMap QueryRegistrations;
SymbolMap ResolvedSymbols;
size_t NotYetResolvedCount;
size_t NotYetReadyCount;
};
/// A symbol table that supports asynchoronous symbol queries.
///
/// 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 {
friend class AsynchronousSymbolQuery;
friend class ExecutionSession;
friend class ExecutionSessionBase;
friend class MaterializationResponsibility;
public:
using FallbackDefinitionGeneratorFunction =
std::function<SymbolNameSet(VSO &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;
/// Get the name for this VSO.
const std::string &getName() const { return VSOName; }
/// Get a reference to the ExecutionSession for this VSO.
ExecutionSessionBase &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.
void setFallbackDefinitionGenerator(
FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) {
this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator);
}
/// Set the search order to be used when fixing up definitions in VSO.
/// This will replace the previous search order, and apply to any symbol
/// resolutions made for definitions in this VSO 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 SearchThisVSOFirst 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
/// 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);
/// Add the given VSO to the search order for definitions in this VSO.
void addToSearchOrder(VSO &V);
/// 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);
/// Remove the given VSO from the search order for this VSO if it is
/// present. Otherwise this operation is a no-op.
void removeFromSearchOrder(VSO &V);
/// 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); });
}
/// 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");
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();
});
}
/// Search the given VSO 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.
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
/// (once they become available) will be returned via the given Query.
///
/// If any symbol is not found then the unresolved symbols will be returned,
/// and the query will not be applied. The Query is not failed and can be
/// re-used in a subsequent lookup once the symbols have been added, or
/// manually failed.
SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
SymbolNameSet Names);
private:
using AsynchronousSymbolQueryList =
std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
struct UnmaterializedInfo {
UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
: MU(std::move(MU)) {}
std::unique_ptr<MaterializationUnit> MU;
};
using UnmaterializedInfosMap =
std::map<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
struct MaterializingInfo {
AsynchronousSymbolQueryList PendingQueries;
SymbolDependenceMap Dependants;
SymbolDependenceMap UnfinalizedDependencies;
bool IsFinalized = false;
};
using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
using LookupImplActionFlags = enum {
None = 0,
NotifyFullyResolved = 1 << 0U,
NotifyFullyReady = 1 << 1U,
LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
};
VSO(ExecutionSessionBase &ES, std::string Name);
Error defineImpl(MaterializationUnit &MU);
SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
const SymbolNameSet &Names);
void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
SymbolNameSet &Unresolved, MaterializationUnitList &MUs);
void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
SymbolNameSet &Unresolved, MaterializationUnitList &MUs);
LookupImplActionFlags
lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolNameSet &Unresolved);
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);
void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
const SymbolStringPtr &DependantName,
MaterializingInfo &FinalizedMI);
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
void replace(std::unique_ptr<MaterializationUnit> MU);
SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependants);
void resolve(const SymbolMap &Resolved);
void finalize(const SymbolFlagsMap &Finalized);
void notifyFailed(const SymbolNameSet &FailedSymbols);
ExecutionSessionBase &ES;
std::string VSOName;
SymbolMap Symbols;
UnmaterializedInfosMap UnmaterializedInfos;
MaterializingInfosMap MaterializingInfos;
FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
VSOList SearchOrder;
};
/// An ExecutionSession represents a running JIT program.
class ExecutionSession : public ExecutionSessionBase {
public:
using ErrorReporter = std::function<void(Error)>;
using DispatchMaterializationFunction =
std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
/// Construct an ExecutionEngine.
///
/// SymbolStringPools may be shared between ExecutionSessions.
ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr)
: ExecutionSessionBase(std::move(SSP)) {}
/// Add a new VSO to this ExecutionSession.
VSO &createVSO(std::string Name);
private:
std::vector<std::unique_ptr<VSO>> VSOs;
};
/// 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);
/// Look up a symbol by searching a list of VSOs.
Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name);
/// Mangles symbol names then uniques them in the context of an
/// ExecutionSession.
class MangleAndInterner {
public:
MangleAndInterner(ExecutionSessionBase &ES, const DataLayout &DL);
SymbolStringPtr operator()(StringRef Name);
private:
ExecutionSessionBase &ES;
const DataLayout &DL;
};
} // End namespace orc
} // End namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H