Update clang to r339409.
Change-Id: I800772d2d838223be1f6b40d490c4591b937fca2
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h b/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h
index 7932688..b61cb24 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -60,7 +60,7 @@
} // end namespace object
-/// \brief Helper class for helping synchronize access to the global address map
+/// Helper class for helping synchronize access to the global address map
/// table. Access to this class should be serialized under a mutex.
class ExecutionEngineState {
public:
@@ -86,7 +86,7 @@
return GlobalAddressReverseMap;
}
- /// \brief Erase an entry from the mapping table.
+ /// Erase an entry from the mapping table.
///
/// \returns The address that \p ToUnmap was happed to.
uint64_t RemoveMapping(StringRef Name);
@@ -94,7 +94,7 @@
using FunctionCreator = std::function<void *(const std::string &)>;
-/// \brief Abstract interface for implementation execution of LLVM modules,
+/// Abstract interface for implementation execution of LLVM modules,
/// designed to support both interpreter and just-in-time (JIT) compiler
/// implementations.
class ExecutionEngine {
@@ -634,7 +634,7 @@
return *this;
}
- // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default.
+ // Use OrcMCJITReplacement instead of MCJIT. Off by default.
void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) {
this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
}
@@ -642,7 +642,7 @@
void setEmulatedTLS(bool EmulatedTLS) {
this->EmulatedTLS = EmulatedTLS;
}
-
+
TargetMachine *selectTarget();
/// selectTarget - Pick a target either via -march or by guessing the native
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h
index ff7840f..1ce772c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h
@@ -15,9 +15,11 @@
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
+#include "llvm-c/ExecutionEngine.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/CBindingWrapping.h"
#include <cstdint>
#include <vector>
@@ -115,10 +117,21 @@
}
#endif // USE_OPROFILE
+#if LLVM_USE_PERF
+ static JITEventListener *createPerfJITEventListener();
+#else
+ static JITEventListener *createPerfJITEventListener()
+ {
+ return nullptr;
+ }
+#endif // USE_PERF
+
private:
virtual void anchor();
};
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITEventListener, LLVMJITEventListenerRef)
+
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
index 86ab173..0e33f01 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
@@ -32,14 +32,14 @@
namespace object {
-class BasicSymbolRef;
+class SymbolRef;
} // end namespace object
-/// @brief Represents an address in the target process's address space.
+/// Represents an address in the target process's address space.
using JITTargetAddress = uint64_t;
-/// @brief Flags for symbols in the JIT.
+/// Flags for symbols in the JIT.
class JITSymbolFlags {
public:
using UnderlyingType = uint8_t;
@@ -52,63 +52,77 @@
Common = 1U << 2,
Absolute = 1U << 3,
Exported = 1U << 4,
- NotMaterialized = 1U << 5
+ Callable = 1U << 5,
+ Lazy = 1U << 6,
+ Materializing = 1U << 7
};
static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig) {
- return static_cast<FlagNames>(Orig.Flags & ~NotMaterialized);
+ return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing);
}
- /// @brief Default-construct a JITSymbolFlags instance.
+ /// Default-construct a JITSymbolFlags instance.
JITSymbolFlags() = default;
- /// @brief Construct a JITSymbolFlags instance from the given flags.
+ /// Construct a JITSymbolFlags instance from the given flags.
JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
- /// @brief Construct a JITSymbolFlags instance from the given flags and target
+ /// Construct a JITSymbolFlags instance from the given flags and target
/// flags.
JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
: Flags(Flags), TargetFlags(TargetFlags) {}
- /// @brief Return true if there was an error retrieving this symbol.
+ /// Return true if there was an error retrieving this symbol.
bool hasError() const {
return (Flags & HasError) == HasError;
}
- /// @brief Returns true if this symbol has been fully materialized (i.e. is
- /// callable).
- bool isMaterialized() const { return !(Flags & NotMaterialized); }
+ /// Returns true if this is a lazy symbol.
+ /// This flag is used internally by the JIT APIs to track
+ /// materialization states.
+ bool isLazy() const { return Flags & Lazy; }
- /// @brief Returns true if the Weak flag is set.
+ /// Returns true if this symbol is in the process of being
+ /// materialized.
+ bool isMaterializing() const { return Flags & Materializing; }
+
+ /// Returns true if this symbol is fully materialized.
+ /// (i.e. neither lazy, nor materializing).
+ bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); }
+
+ /// Returns true if the Weak flag is set.
bool isWeak() const {
return (Flags & Weak) == Weak;
}
- /// @brief Returns true if the Common flag is set.
+ /// Returns true if the Common flag is set.
bool isCommon() const {
return (Flags & Common) == Common;
}
- /// @brief Returns true if the symbol isn't weak or common.
+ /// Returns true if the symbol isn't weak or common.
bool isStrong() const {
return !isWeak() && !isCommon();
}
- /// @brief Returns true if the Exported flag is set.
+ /// Returns true if the Exported flag is set.
bool isExported() const {
return (Flags & Exported) == Exported;
}
- /// @brief Implicitly convert to the underlying flags type.
+ /// Returns true if the given symbol is known to be callable.
+ bool isCallable() const { return (Flags & Callable) == Callable; }
+
+ /// Implicitly convert to the underlying flags type.
operator UnderlyingType&() { return Flags; }
- /// @brief Implicitly convert to the underlying flags type.
+ /// Implicitly convert to the underlying flags type.
operator const UnderlyingType&() const { return Flags; }
- /// @brief Return a reference to the target-specific flags.
+ /// Return a reference to the target-specific flags.
TargetFlagsType& getTargetFlags() { return TargetFlags; }
- /// @brief Return a reference to the target-specific flags.
+ /// Return a reference to the target-specific flags.
const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
/// Construct a JITSymbolFlags value based on the flags of the given global
@@ -117,14 +131,15 @@
/// Construct a JITSymbolFlags value based on the flags of the given libobject
/// symbol.
- static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol);
+ static Expected<JITSymbolFlags>
+ fromObjectSymbol(const object::SymbolRef &Symbol);
private:
UnderlyingType Flags = None;
TargetFlagsType TargetFlags = 0;
};
-/// @brief ARM-specific JIT symbol flags.
+/// ARM-specific JIT symbol flags.
/// FIXME: This should be moved into a target-specific header.
class ARMJITSymbolFlags {
public:
@@ -137,62 +152,65 @@
operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
- static ARMJITSymbolFlags fromObjectSymbol(
- const object::BasicSymbolRef &Symbol);
+ static ARMJITSymbolFlags fromObjectSymbol(const object::SymbolRef &Symbol);
+
private:
JITSymbolFlags::TargetFlagsType Flags = 0;
};
-/// @brief Represents a symbol that has been evaluated to an address already.
+/// Represents a symbol that has been evaluated to an address already.
class JITEvaluatedSymbol {
public:
JITEvaluatedSymbol() = default;
- /// @brief Create a 'null' symbol.
+ /// Create a 'null' symbol.
JITEvaluatedSymbol(std::nullptr_t) {}
- /// @brief Create a symbol for the given address and flags.
+ /// Create a symbol for the given address and flags.
JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
: Address(Address), Flags(Flags) {}
- /// @brief An evaluated symbol converts to 'true' if its address is non-zero.
+ /// An evaluated symbol converts to 'true' if its address is non-zero.
explicit operator bool() const { return Address != 0; }
- /// @brief Return the address of this symbol.
+ /// Return the address of this symbol.
JITTargetAddress getAddress() const { return Address; }
- /// @brief Return the flags for this symbol.
+ /// Return the flags for this symbol.
JITSymbolFlags getFlags() const { return Flags; }
+ /// Set the flags for this symbol.
+ void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); }
+
private:
JITTargetAddress Address = 0;
JITSymbolFlags Flags;
};
-/// @brief Represents a symbol in the JIT.
+/// Represents a symbol in the JIT.
class JITSymbol {
public:
using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
- /// @brief Create a 'null' symbol, used to represent a "symbol not found"
+ /// Create a 'null' symbol, used to represent a "symbol not found"
/// result from a successful (non-erroneous) lookup.
JITSymbol(std::nullptr_t)
: CachedAddr(0) {}
- /// @brief Create a JITSymbol representing an error in the symbol lookup
+ /// Create a JITSymbol representing an error in the symbol lookup
/// process (e.g. a network failure during a remote lookup).
JITSymbol(Error Err)
: Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
- /// @brief Create a symbol for a definition with a known address.
+ /// Create a symbol for a definition with a known address.
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
: CachedAddr(Addr), Flags(Flags) {}
- /// @brief Construct a JITSymbol from a JITEvaluatedSymbol.
+ /// Construct a JITSymbol from a JITEvaluatedSymbol.
JITSymbol(JITEvaluatedSymbol Sym)
: CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
- /// @brief Create a symbol for a definition that doesn't have a known address
+ /// Create a symbol for a definition that doesn't have a known address
/// yet.
/// @param GetAddress A functor to materialize a definition (fixing the
/// address) on demand.
@@ -232,19 +250,19 @@
CachedAddr.~JITTargetAddress();
}
- /// @brief Returns true if the symbol exists, false otherwise.
+ /// Returns true if the symbol exists, false otherwise.
explicit operator bool() const {
return !Flags.hasError() && (CachedAddr || GetAddress);
}
- /// @brief Move the error field value out of this JITSymbol.
+ /// Move the error field value out of this JITSymbol.
Error takeError() {
if (Flags.hasError())
return std::move(Err);
return Error::success();
}
- /// @brief Get the address of the symbol in the target address space. Returns
+ /// Get the address of the symbol in the target address space. Returns
/// '0' if the symbol does not exist.
Expected<JITTargetAddress> getAddress() {
assert(!Flags.hasError() && "getAddress called on error value");
@@ -270,7 +288,7 @@
JITSymbolFlags Flags;
};
-/// @brief Symbol resolution interface.
+/// Symbol resolution interface.
///
/// Allows symbol flags and addresses to be looked up by name.
/// Symbol queries are done in bulk (i.e. you request resolution of a set of
@@ -284,14 +302,14 @@
virtual ~JITSymbolResolver() = default;
- /// @brief Returns the fully resolved address and flags for each of the given
+ /// Returns the fully resolved address and flags for each of the given
/// symbols.
///
/// This method will return an error if any of the given symbols can not be
/// resolved, or if the resolution process itself triggers an error.
virtual Expected<LookupResult> lookup(const LookupSet &Symbols) = 0;
- /// @brief Returns the symbol flags for each of the given symbols.
+ /// Returns the symbol flags for each of the given symbols.
///
/// This method does NOT return an error if any of the given symbols is
/// missing. Instead, that symbol will be left out of the result map.
@@ -301,15 +319,15 @@
virtual void anchor();
};
-/// \brief Legacy symbol resolution interface.
+/// Legacy symbol resolution interface.
class LegacyJITSymbolResolver : public JITSymbolResolver {
public:
- /// @brief Performs lookup by, for each symbol, first calling
+ /// Performs lookup by, for each symbol, first calling
/// findSymbolInLogicalDylib and if that fails calling
/// findSymbol.
Expected<LookupResult> lookup(const LookupSet &Symbols) final;
- /// @brief Performs flags lookup by calling findSymbolInLogicalDylib and
+ /// Performs flags lookup by calling findSymbolInLogicalDylib and
/// returning the flags value for that symbol.
Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) final;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/linux-x64/clang/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
deleted file mode 100644
index 0f00ad0..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares a wrapper class to hold the memory into which an
-// object will be generated.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
-#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-/// \brief SmallVector-backed MemoryBuffer instance.
-///
-/// This class enables efficient construction of MemoryBuffers from SmallVector
-/// instances. This is useful for MCJIT and Orc, where object files are streamed
-/// into SmallVectors, then inspected using ObjectFile (which takes a
-/// MemoryBuffer).
-class ObjectMemoryBuffer : public MemoryBuffer {
-public:
-
- /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value.
- ///
- /// FIXME: It'd be nice for this to be a non-templated constructor taking a
- /// SmallVectorImpl here instead of a templated one taking a SmallVector<N>,
- /// but SmallVector's move-construction/assignment currently only take
- /// SmallVectors. If/when that is fixed we can simplify this constructor and
- /// the following one.
- ObjectMemoryBuffer(SmallVectorImpl<char> &&SV)
- : SV(std::move(SV)), BufferName("<in-memory object>") {
- init(this->SV.begin(), this->SV.end(), false);
- }
-
- /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector
- /// r-value and StringRef.
- ObjectMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
- : SV(std::move(SV)), BufferName(Name) {
- init(this->SV.begin(), this->SV.end(), false);
- }
-
- StringRef getBufferIdentifier() const override { return BufferName; }
-
- BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
-
-private:
- SmallVector<char, 0> SV;
- std::string BufferName;
-};
-
-} // namespace llvm
-
-#endif
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index a64a6dd..8bd21a0 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -20,9 +20,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/Attributes.h"
@@ -57,7 +58,47 @@
namespace orc {
-/// @brief Compile-on-demand layer.
+class ExtractingIRMaterializationUnit;
+
+class CompileOnDemandLayer2 : public IRLayer {
+ friend class ExtractingIRMaterializationUnit;
+
+public:
+ /// Builder for IndirectStubsManagers.
+ using IndirectStubsManagerBuilder =
+ std::function<std::unique_ptr<IndirectStubsManager>()>;
+
+ using GetAvailableContextFunction = std::function<LLVMContext &()>;
+
+ CompileOnDemandLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
+ JITCompileCallbackManager &CCMgr,
+ IndirectStubsManagerBuilder BuildIndirectStubsManager,
+ GetAvailableContextFunction GetAvailableContext);
+
+ Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) override;
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) override;
+
+private:
+ using StubManagersMap =
+ std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>;
+
+ IndirectStubsManager &getStubsManager(const VSO &V);
+
+ void emitExtractedFunctionsModule(MaterializationResponsibility R,
+ std::unique_ptr<Module> M);
+
+ mutable std::mutex CODLayerMutex;
+
+ IRLayer &BaseLayer;
+ JITCompileCallbackManager &CCMgr;
+ IndirectStubsManagerBuilder BuildIndirectStubsManager;
+ StubManagersMap StubsMgrs;
+ GetAvailableContextFunction GetAvailableContext;
+};
+
+/// Compile-on-demand layer.
///
/// When a module is added to this layer a stub is created for each of its
/// function definitions. The stubs and other global values are immediately
@@ -196,10 +237,10 @@
public:
- /// @brief Module partitioning functor.
+ /// Module partitioning functor.
using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
- /// @brief Builder for IndirectStubsManagers.
+ /// Builder for IndirectStubsManagers.
using IndirectStubsManagerBuilderT =
std::function<std::unique_ptr<IndirectStubsMgrT>()>;
@@ -209,7 +250,7 @@
using SymbolResolverSetter =
std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
- /// @brief Construct a compile-on-demand layer instance.
+ /// Construct a compile-on-demand layer instance.
CompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer,
SymbolResolverGetter GetSymbolResolver,
SymbolResolverSetter SetSymbolResolver,
@@ -230,7 +271,7 @@
consumeError(removeModule(LogicalDylibs.begin()->first));
}
- /// @brief Add a module to the compile-on-demand layer.
+ /// Add a module to the compile-on-demand layer.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
@@ -242,12 +283,12 @@
return addLogicalModule(I->second, std::move(M));
}
- /// @brief Add extra modules to an existing logical module.
+ /// Add extra modules to an existing logical module.
Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
return addLogicalModule(LogicalDylibs[K], std::move(M));
}
- /// @brief Remove the module represented by the given key.
+ /// Remove the module represented by the given key.
///
/// This will remove all modules in the layers below that were derived from
/// the module represented by K.
@@ -259,7 +300,7 @@
return Err;
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
@@ -275,7 +316,7 @@
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of a symbol provided by this layer, or some layer
+ /// Get the address of a symbol provided by this layer, or some layer
/// below this one.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
@@ -283,7 +324,7 @@
return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
}
- /// @brief Update the stub for the given function to point at FnBodyAddr.
+ /// Update the stub for the given function to point at FnBodyAddr.
/// This can be used to support re-optimization.
/// @return true if the function exists and the stub is updated, false
/// otherwise.
@@ -316,7 +357,7 @@
// simplifying symbol lookup.
LD.StaticRenamer.rename(*SrcMPtr);
- // Bump the linkage and rename any anonymous/privote members in SrcM to
+ // Bump the linkage and rename any anonymous/private members in SrcM to
// ensure that everything will resolve properly after we partition SrcM.
makeAllSymbolsExternallyAccessible(*SrcMPtr);
@@ -349,22 +390,21 @@
// Create a callback, associate it with the stub for the function,
// and set the compile action to compile the partition containing the
// function.
- if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) {
- auto &CCInfo = *CCInfoOrErr;
+ auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress {
+ if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
+ return *FnImplAddrOrErr;
+ else {
+ // FIXME: Report error, return to 'abort' or something similar.
+ consumeError(FnImplAddrOrErr.takeError());
+ return 0;
+ }
+ };
+ if (auto CCAddr =
+ CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
StubInits[MangledName] =
- std::make_pair(CCInfo.getAddress(),
- JITSymbolFlags::fromGlobalValue(F));
- CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
- if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
- return *FnImplAddrOrErr;
- else {
- // FIXME: Report error, return to 'abort' or something similar.
- consumeError(FnImplAddrOrErr.takeError());
- return 0;
- }
- });
- } else
- return CCInfoOrErr.takeError();
+ std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
+ else
+ return CCAddr.takeError();
}
if (auto Err = LD.StubsMgr->createStubs(StubInits))
@@ -402,9 +442,8 @@
// Initializers may refer to functions declared (but not defined) in this
// module. Build a materializer to clone decls on demand.
- Error MaterializerErrors = Error::success();
auto Materializer = createLambdaMaterializer(
- [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* {
+ [&LD, &GVsM](Value *V) -> Value* {
if (auto *F = dyn_cast<Function>(V)) {
// Decls in the original module just get cloned.
if (F->isDeclaration())
@@ -416,18 +455,8 @@
const DataLayout &DL = GVsM->getDataLayout();
std::string FName = mangle(F->getName(), DL);
unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
- JITTargetAddress StubAddr = 0;
-
- // Get the address for the stub. If we encounter an error while
- // doing so, stash it in the MaterializerErrors variable and use a
- // null address as a placeholder.
- if (auto StubSym = LD.StubsMgr->findStub(FName, false)) {
- if (auto StubAddrOrErr = StubSym.getAddress())
- StubAddr = *StubAddrOrErr;
- else
- MaterializerErrors = joinErrors(std::move(MaterializerErrors),
- StubAddrOrErr.takeError());
- }
+ JITTargetAddress StubAddr =
+ LD.StubsMgr->findStub(FName, false).getAddress();
ConstantInt *StubAddrCI =
ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
@@ -456,15 +485,10 @@
NewA->setAliasee(cast<Constant>(Init));
}
- if (MaterializerErrors)
- return MaterializerErrors;
-
// Build a resolver for the globals module and add it to the base layer.
auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
if (auto Sym = LD.StubsMgr->findStub(Name, false))
return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
return Sym;
@@ -475,25 +499,35 @@
};
auto GVsResolver = createSymbolResolver(
- [&LD, LegacyLookup](SymbolFlagsMap &SymbolFlags,
- const SymbolNameSet &Symbols) {
- auto NotFoundViaLegacyLookup =
- lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup);
+ [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
+ auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
- if (!NotFoundViaLegacyLookup) {
- logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(),
+ if (!SymbolFlags) {
+ logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
"CODLayer/GVsResolver flags lookup failed: ");
- SymbolFlags.clear();
- return SymbolNameSet();
+ return SymbolFlagsMap();
}
- return LD.BackingResolver->lookupFlags(SymbolFlags,
- *NotFoundViaLegacyLookup);
+ if (SymbolFlags->size() == Symbols.size())
+ return *SymbolFlags;
+
+ SymbolNameSet NotFoundViaLegacyLookup;
+ for (auto &S : Symbols)
+ if (!SymbolFlags->count(S))
+ NotFoundViaLegacyLookup.insert(S);
+ auto SymbolFlags2 =
+ LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+
+ for (auto &KV : SymbolFlags2)
+ (*SymbolFlags)[KV.first] = std::move(KV.second);
+
+ return *SymbolFlags;
},
- [&LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) {
+ [this, &LD,
+ LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) {
auto NotFoundViaLegacyLookup =
- lookupWithLegacyFn(*Query, Symbols, LegacyLookup);
+ lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
});
@@ -634,23 +668,34 @@
// Create memory manager and symbol resolver.
auto Resolver = createSymbolResolver(
- [&LD, LegacyLookup](SymbolFlagsMap &SymbolFlags,
- const SymbolNameSet &Symbols) {
- auto NotFoundViaLegacyLookup =
- lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup);
- if (!NotFoundViaLegacyLookup) {
- logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(),
+ [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
+ auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
+ if (!SymbolFlags) {
+ logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
"CODLayer/SubResolver flags lookup failed: ");
- SymbolFlags.clear();
- return SymbolNameSet();
+ return SymbolFlagsMap();
}
- return LD.BackingResolver->lookupFlags(SymbolFlags,
- *NotFoundViaLegacyLookup);
+
+ if (SymbolFlags->size() == Symbols.size())
+ return *SymbolFlags;
+
+ SymbolNameSet NotFoundViaLegacyLookup;
+ for (auto &S : Symbols)
+ if (!SymbolFlags->count(S))
+ NotFoundViaLegacyLookup.insert(S);
+
+ auto SymbolFlags2 =
+ LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+
+ for (auto &KV : SymbolFlags2)
+ (*SymbolFlags)[KV.first] = std::move(KV.second);
+
+ return *SymbolFlags;
},
- [&LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
- SymbolNameSet Symbols) {
+ [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
+ SymbolNameSet Symbols) {
auto NotFoundViaLegacyLookup =
- lookupWithLegacyFn(*Q, Symbols, LegacyLookup);
+ lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
return LD.BackingResolver->lookup(Q,
std::move(NotFoundViaLegacyLookup));
});
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index a8050ff..213a591 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -16,13 +16,14 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
-#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
@@ -35,35 +36,21 @@
namespace orc {
-/// @brief Simple compile functor: Takes a single IR module and returns an
-/// ObjectFile.
+/// Simple compile functor: Takes a single IR module and returns an ObjectFile.
+/// This compiler supports a single compilation thread and LLVMContext only.
+/// For multithreaded compilation, use MultiThreadedSimpleCompiler below.
class SimpleCompiler {
-private:
- class SmallVectorMemoryBuffer : public MemoryBuffer {
- public:
- SmallVectorMemoryBuffer(SmallVector<char, 0> Buffer)
- : Buffer(std::move(Buffer)) {
- init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
- false);
- }
-
- BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
-
- private:
- SmallVector<char, 0> Buffer;
- };
-
public:
using CompileResult = std::unique_ptr<MemoryBuffer>;
- /// @brief Construct a simple compile functor with the given target.
+ /// Construct a simple compile functor with the given target.
SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
: TM(TM), ObjCache(ObjCache) {}
- /// @brief Set an ObjectCache to query before compiling.
+ /// Set an ObjectCache to query before compiling.
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
- /// @brief Compile a Module to an ObjectFile.
+ /// Compile a Module to an ObjectFile.
CompileResult operator()(Module &M) {
CompileResult CachedObject = tryToLoadFromObjectCache(M);
if (CachedObject)
@@ -114,6 +101,29 @@
ObjectCache *ObjCache = nullptr;
};
+/// A thread-safe version of SimpleCompiler.
+///
+/// This class creates a new TargetMachine and SimpleCompiler instance for each
+/// compile.
+class MultiThreadedSimpleCompiler {
+public:
+ MultiThreadedSimpleCompiler(JITTargetMachineBuilder JTMB,
+ ObjectCache *ObjCache = nullptr)
+ : JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
+
+ void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; }
+
+ std::unique_ptr<MemoryBuffer> operator()(Module &M) {
+ auto TM = cantFail(JTMB.createTargetMachine());
+ SimpleCompiler C(*TM, ObjCache);
+ return C(M);
+ }
+
+private:
+ JITTargetMachineBuilder JTMB;
+ ObjectCache *ObjCache = nullptr;
+};
+
} // end namespace orc
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
index 26fec8b..8456dff 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
@@ -14,9 +14,12 @@
#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>
@@ -25,139 +28,173 @@
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;
-class VSO;
-
-/// @brief A set of symbol names (represented by SymbolStringPtrs for
+/// A set of symbol names (represented by SymbolStringPtrs for
// efficiency).
using SymbolNameSet = std::set<SymbolStringPtr>;
-/// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbols
+/// 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>;
-/// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
+/// 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>;
-/// @brief A symbol query that returns results via a callback when results are
-/// ready.
+/// 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.
///
-/// makes a callback when all symbols are available.
-class AsynchronousSymbolQuery {
+/// 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:
- /// @brief Callback to notify client that symbols have been resolved.
- using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
+ MaterializationResponsibility(MaterializationResponsibility &&) = default;
+ MaterializationResponsibility &
+ operator=(MaterializationResponsibility &&) = default;
- /// @brief Callback to notify client that symbols are ready for execution.
- using SymbolsReadyCallback = std::function<void(Error)>;
+ /// Destruct a MaterializationResponsibility instance. In debug mode
+ /// this asserts that all symbols being tracked have been either
+ /// finalized or notified of an error.
+ ~MaterializationResponsibility();
- /// @brief Create a query for the given symbols, notify-resolved and
- /// notify-ready callbacks.
- AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
- SymbolsResolvedCallback NotifySymbolsResolved,
- SymbolsReadyCallback NotifySymbolsReady);
+ /// Returns the target VSO that these symbols are being materialized
+ /// into.
+ VSO &getTargetVSO() const { return V; }
- /// @brief Notify client that the query failed.
- ///
- /// If the notify-resolved callback has not been made yet, then it is called
- /// with the given error, and the notify-finalized callback is never made.
- ///
- /// If the notify-resolved callback has already been made then then the
- /// notify-finalized callback is called with the given error.
- ///
- /// It is illegal to call setFailed after both callbacks have been made.
- void setFailed(Error Err);
+ /// Returns the symbol flags map for this responsibility instance.
+ SymbolFlagsMap getSymbols() { return SymbolFlags; }
- /// @brief Set the resolved symbol information for the given symbol name.
- ///
- /// If this symbol was the last one not resolved, this will trigger a call to
- /// the notify-finalized callback passing the completed sybol map.
- void setDefinition(SymbolStringPtr Name, JITEvaluatedSymbol Sym);
+ /// 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();
- /// @brief Notify the query that a requested symbol is ready for execution.
+ /// 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 decrements the query's internal count of not-yet-ready symbols. If
- /// this call to notifySymbolFinalized sets the counter to zero, it will call
- /// the notify-finalized callback with Error::success as the value.
- void notifySymbolFinalized();
+ /// 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:
- SymbolMap Symbols;
- size_t OutstandingResolutions = 0;
- size_t OutstandingFinalizations = 0;
- SymbolsResolvedCallback NotifySymbolsResolved;
- SymbolsReadyCallback NotifySymbolsReady;
+ /// Create a MaterializationResponsibility for the given VSO and
+ /// initial symbols.
+ MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
+
+ VSO &V;
+ SymbolFlagsMap SymbolFlags;
};
-/// @brief SymbolResolver is a composable interface for looking up symbol flags
-/// and addresses using the AsynchronousSymbolQuery type. It will
-/// eventually replace the LegacyJITSymbolResolver interface as the
-/// stardard ORC symbol resolver type.
-class SymbolResolver {
-public:
- virtual ~SymbolResolver() = default;
-
- /// @brief Returns the flags for each symbol in Symbols that can be found,
- /// along with the set of symbol that could not be found.
- virtual SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
- const SymbolNameSet &Symbols) = 0;
-
- /// @brief 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.
- virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) = 0;
-
-private:
- virtual void anchor();
-};
-
-/// @brief Implements SymbolResolver with a pair of supplied function objects
-/// for convenience. See createSymbolResolver.
-template <typename LookupFlagsFn, typename LookupFn>
-class LambdaSymbolResolver final : public SymbolResolver {
-public:
- template <typename LookupFlagsFnRef, typename LookupFnRef>
- LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
- : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
- Lookup(std::forward<LookupFnRef>(Lookup)) {}
-
- SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
- const SymbolNameSet &Symbols) final {
- return LookupFlags(Flags, Symbols);
- }
-
- SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) final {
- return Lookup(std::move(Query), std::move(Symbols));
- }
-
-private:
- LookupFlagsFn LookupFlags;
- LookupFn Lookup;
-};
-
-/// @brief Creates a SymbolResolver implementation from the pair of supplied
-/// function objects.
-template <typename LookupFlagsFn, typename LookupFn>
-std::unique_ptr<LambdaSymbolResolver<
- typename std::remove_cv<
- typename std::remove_reference<LookupFlagsFn>::type>::type,
- typename std::remove_cv<
- typename std::remove_reference<LookupFn>::type>::type>>
-createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
- using LambdaSymbolResolverImpl = LambdaSymbolResolver<
- typename std::remove_cv<
- typename std::remove_reference<LookupFlagsFn>::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));
-}
-
-/// @brief A MaterializationUnit represents a set of symbol definitions that can
+/// A MaterializationUnit represents a set of symbol definitions that can
/// be materialized as a group, or individually discarded (when
/// overriding definitions are encountered).
///
@@ -167,226 +204,585 @@
/// definition is added or already present.
class MaterializationUnit {
public:
+ MaterializationUnit(SymbolFlagsMap InitalSymbolFlags)
+ : SymbolFlags(std::move(InitalSymbolFlags)) {}
+
virtual ~MaterializationUnit() {}
- /// @brief Return the set of symbols that this source provides.
- virtual SymbolFlagsMap getSymbols() = 0;
+ /// Return the set of symbols that this source provides.
+ const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
- /// @brief Implementations of this method should materialize all symbols
- /// in the materialzation unit, except for those that have been
- /// previously discarded.
- virtual Error materialize(VSO &V) = 0;
+ /// Called by materialization dispatchers (see
+ /// ExecutionSession::DispatchMaterializationFunction) to trigger
+ /// materialization of this MaterializationUnit.
+ void doMaterialize(VSO &V) {
+ materialize(MaterializationResponsibility(V, std::move(SymbolFlags)));
+ }
- /// @brief 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(VSO &V, SymbolStringPtr Name) = 0;
+ /// 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;
};
-/// @brief Represents a dynamic linkage unit in a JIT process.
+using MaterializationUnitList =
+ std::vector<std::unique_ptr<MaterializationUnit>>;
+
+/// A MaterializationUnit implementation for pre-existing absolute symbols.
///
-/// VSO acts as a symbol table (symbol definitions can be set and the dylib
-/// queried to find symbol addresses) and as a key for tracking resources
-/// (since a VSO's address is fixed).
-class VSO {
- friend class ExecutionSession;
+/// 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);
+
+class ReexportsFallbackDefinitionGenerator {
+public:
+ using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+ ReexportsFallbackDefinitionGenerator(VSO &BackingVSO, SymbolPredicate Allow);
+ SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+
+private:
+ VSO &BackingVSO;
+ SymbolPredicate Allow;
+};
+
+/// Base utilities for ExecutionSession.
+class ExecutionSessionBase {
+ // FIXME: Remove this when we remove the old ORC layers.
+ friend class VSO;
public:
- enum RelativeLinkageStrength {
- NewDefinitionIsStronger,
- DuplicateDefinition,
- ExistingDefinitionIsStronger
- };
+ /// For reporting errors.
+ using ErrorReporter = std::function<void(Error)>;
- using SetDefinitionsResult =
- std::map<SymbolStringPtr, RelativeLinkageStrength>;
+ /// For dispatching MaterializationUnit::materialize calls.
+ using DispatchMaterializationFunction =
+ std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
- using MaterializationUnitList =
- std::vector<std::unique_ptr<MaterializationUnit>>;
+ /// 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>()) {}
- struct LookupResult {
- MaterializationUnitList MaterializationUnits;
- SymbolNameSet UnresolvedSymbols;
- };
+ /// Returns the SymbolStringPool for this ExecutionSession.
+ SymbolStringPool &getSymbolStringPool() const { return *SSP; }
- VSO() = default;
+ /// 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;
- /// @brief Compare new linkage with existing linkage.
- static RelativeLinkageStrength
- compareLinkage(Optional<JITSymbolFlags> OldFlags, JITSymbolFlags NewFlags);
+ /// Get the name for this VSO.
+ const std::string &getName() const { return VSOName; }
- /// @brief Compare new linkage with an existing symbol's linkage.
- RelativeLinkageStrength compareLinkage(SymbolStringPtr Name,
- JITSymbolFlags NewFlags) const;
+ /// Get a reference to the ExecutionSession for this VSO.
+ ExecutionSessionBase &getExecutionSession() const { return ES; }
- /// @brief Adds the given symbols to the mapping as resolved, finalized
- /// symbols.
+ /// 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).
///
- /// FIXME: We can take this by const-ref once symbol-based laziness is
- /// removed.
- Error define(SymbolMap NewSymbols);
-
- /// @brief Adds the given symbols to the mapping as lazy symbols.
- Error defineLazy(std::unique_ptr<MaterializationUnit> Source);
-
- /// @brief Add the given symbol/address mappings to the dylib, but do not
- /// mark the symbols as finalized yet.
- void resolve(SymbolMap SymbolValues);
-
- /// @brief Finalize the given symbols.
- void finalize(SymbolNameSet SymbolsToFinalize);
-
- /// @brief Look up the flags for the given symbols.
+ /// 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).
///
- /// Returns the flags for the give symbols, together with the set of symbols
- /// not found.
- SymbolNameSet lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Symbols);
+ /// 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);
- /// @brief Apply the given query to the given symbols in this VSO.
+ /// 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.
///
- /// For symbols in this VSO that have already been materialized, their address
- /// will be set in the query immediately.
- ///
- /// For symbols in this VSO that have not been materialized, the query will be
- /// recorded and the source for those symbols (plus the set of symbols to be
- /// materialized by that source) will be returned as the MaterializationWork
- /// field of the LookupResult.
- ///
- /// Any symbols not found in this VSO will be returned in the
- /// UnresolvedSymbols field of the LookupResult.
- LookupResult lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols);
+ /// 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:
- class MaterializationInfo {
- public:
- using QueryList = std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
+ using AsynchronousSymbolQueryList =
+ std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
- MaterializationInfo(size_t SymbolsRemaining,
- std::unique_ptr<MaterializationUnit> MU);
+ struct UnmaterializedInfo {
+ UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
+ : MU(std::move(MU)) {}
- uint64_t SymbolsRemaining;
std::unique_ptr<MaterializationUnit> MU;
- SymbolMap Symbols;
- std::map<SymbolStringPtr, QueryList> PendingResolution;
- std::map<SymbolStringPtr, QueryList> PendingFinalization;
};
- using MaterializationInfoSet = std::set<std::unique_ptr<MaterializationInfo>>;
+ using UnmaterializedInfosMap =
+ std::map<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
- using MaterializationInfoIterator = MaterializationInfoSet::iterator;
-
- class SymbolTableEntry {
- public:
- SymbolTableEntry(JITSymbolFlags SymbolFlags,
- MaterializationInfoIterator MaterializationInfoItr);
- SymbolTableEntry(JITEvaluatedSymbol Sym);
- SymbolTableEntry(SymbolTableEntry &&Other);
- ~SymbolTableEntry();
-
- SymbolTableEntry &operator=(JITEvaluatedSymbol Sym);
-
- JITSymbolFlags getFlags() const;
- void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
- MaterializationInfoIterator NewMaterializationInfoItr);
- std::unique_ptr<MaterializationUnit>
- query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
- void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
- void finalize(VSO &V, SymbolStringPtr Name);
- void discard(VSO &V, SymbolStringPtr Name);
-
- private:
- void destroy();
-
- JITSymbolFlags Flags;
- MaterializationInfoIterator MII;
- union {
- JITTargetAddress Address;
- MaterializationInfoIterator MaterializationInfoItr;
- };
+ struct MaterializingInfo {
+ AsynchronousSymbolQueryList PendingQueries;
+ SymbolDependenceMap Dependants;
+ SymbolDependenceMap UnfinalizedDependencies;
+ bool IsFinalized = false;
};
- std::map<SymbolStringPtr, SymbolTableEntry> Symbols;
- MaterializationInfoSet MaterializationInfos;
+ 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;
};
-/// @brief An ExecutionSession represents a running JIT program.
-class ExecutionSession {
+/// An ExecutionSession represents a running JIT program.
+class ExecutionSession : public ExecutionSessionBase {
public:
using ErrorReporter = std::function<void(Error)>;
- /// @brief Construct an ExecutionEngine.
+ using DispatchMaterializationFunction =
+ std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
+
+ /// Construct an ExecutionEngine.
///
/// SymbolStringPools may be shared between ExecutionSessions.
- ExecutionSession(SymbolStringPool &SSP);
+ ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr)
+ : ExecutionSessionBase(std::move(SSP)) {}
- /// @brief Returns the SymbolStringPool for this ExecutionSession.
- SymbolStringPool &getSymbolStringPool() const { return SSP; }
-
- /// @brief Set the error reporter function.
- void setErrorReporter(ErrorReporter ReportError) {
- this->ReportError = std::move(ReportError);
- }
-
- /// @brief Report a error for this execution session.
- ///
- /// Unhandled errors can be sent here to log them.
- void reportError(Error Err) { ReportError(std::move(Err)); }
-
- /// @brief Allocate a module key for a new module to add to the JIT.
- VModuleKey allocateVModule();
-
- /// @brief 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);
-
-public:
- static void logErrorsToStdErr(Error Err);
-
- SymbolStringPool &SSP;
- VModuleKey LastKey = 0;
- ErrorReporter ReportError = logErrorsToStdErr;
-};
-
-/// Runs Materializers on the current thread and reports errors to the given
-/// ExecutionSession.
-class MaterializeOnCurrentThread {
-public:
- MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {}
-
- void operator()(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
- if (auto Err = MU->materialize(V))
- ES.reportError(std::move(Err));
- }
+ /// Add a new VSO to this ExecutionSession.
+ VSO &createVSO(std::string Name);
private:
- ExecutionSession &ES;
+ std::vector<std::unique_ptr<VSO>> VSOs;
};
-/// Materialization function object wrapper for the lookup method.
-using MaterializationDispatcher =
- std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> S)>;
+/// 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);
-/// @brief Look up a set of symbols by searching a list of VSOs.
-///
-/// All VSOs in the list should be non-null.
-Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
- MaterializationDispatcher DispatchMaterialization);
+/// Look up a symbol by searching a list of VSOs.
+Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name);
-/// @brief Look up a symbol by searching a list of VSOs.
-Expected<JITEvaluatedSymbol>
-lookup(const std::vector<VSO *> VSOs, SymbolStringPtr Name,
- MaterializationDispatcher DispatchMaterialization);
+/// 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
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index d466df8..e27f6e1 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -20,6 +20,8 @@
#include "llvm/ExecutionEngine/Orc/Core.h"
#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>
@@ -32,18 +34,58 @@
class GlobalVariable;
class Function;
class Module;
+class TargetMachine;
class Value;
namespace orc {
-/// @brief This iterator provides a convenient way to iterate over the elements
+/// 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.
///
/// The easiest way to get hold of instances of this class is to use the
/// getConstructors/getDestructors functions.
class CtorDtorIterator {
public:
- /// @brief Accessor for an element of the global_ctors/global_dtors array.
+ /// Accessor for an element of the global_ctors/global_dtors array.
///
/// This class provides a read-only view of the element with any casts on
/// the function stripped away.
@@ -56,23 +98,23 @@
Value *Data;
};
- /// @brief Construct an iterator instance. If End is true then this iterator
+ /// Construct an iterator instance. If End is true then this iterator
/// acts as the end of the range, otherwise it is the beginning.
CtorDtorIterator(const GlobalVariable *GV, bool End);
- /// @brief Test iterators for equality.
+ /// Test iterators for equality.
bool operator==(const CtorDtorIterator &Other) const;
- /// @brief Test iterators for inequality.
+ /// Test iterators for inequality.
bool operator!=(const CtorDtorIterator &Other) const;
- /// @brief Pre-increment iterator.
+ /// Pre-increment iterator.
CtorDtorIterator& operator++();
- /// @brief Post-increment iterator.
+ /// Post-increment iterator.
CtorDtorIterator operator++(int);
- /// @brief Dereference iterator. The resulting value provides a read-only view
+ /// Dereference iterator. The resulting value provides a read-only view
/// of this element of the global_ctors/global_dtors list.
Element operator*() const;
@@ -81,25 +123,25 @@
unsigned I;
};
-/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// Create an iterator range over the entries of the llvm.global_ctors
/// array.
iterator_range<CtorDtorIterator> getConstructors(const Module &M);
-/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// Create an iterator range over the entries of the llvm.global_ctors
/// array.
iterator_range<CtorDtorIterator> getDestructors(const Module &M);
-/// @brief Convenience class for recording constructor/destructor names for
+/// Convenience class for recording constructor/destructor names for
/// later execution.
template <typename JITLayerT>
class CtorDtorRunner {
public:
- /// @brief Construct a CtorDtorRunner for the given range using the given
+ /// Construct a CtorDtorRunner for the given range using the given
/// name mangling function.
CtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K)
: CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
- /// @brief Run the recorded constructors/destructors through the given JIT
+ /// Run the recorded constructors/destructors through the given JIT
/// layer.
Error runViaLayer(JITLayerT &JITLayer) const {
using CtorDtorTy = void (*)();
@@ -127,7 +169,21 @@
orc::VModuleKey K;
};
-/// @brief Support class for static dtor execution. For hosted (in-process) JITs
+class CtorDtorRunner2 {
+public:
+ CtorDtorRunner2(VSO &V) : V(V) {}
+ void add(iterator_range<CtorDtorIterator> CtorDtors);
+ Error run();
+
+private:
+ using CtorDtorList = std::vector<SymbolStringPtr>;
+ using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
+
+ VSO &V;
+ CtorDtorPriorityMap CtorDtorsByPriority;
+};
+
+/// Support class for static dtor execution. For hosted (in-process) JITs
/// only!
///
/// If a __cxa_atexit function isn't found C++ programs that use static
@@ -142,7 +198,26 @@
/// the client determines that destructors should be run (generally at JIT
/// teardown or after a return from main), the runDestructors method should be
/// called.
-class LocalCXXRuntimeOverrides {
+class LocalCXXRuntimeOverridesBase {
+public:
+ /// Run any destructors recorded by the overriden __cxa_atexit function
+ /// (CXAAtExitOverride).
+ void runDestructors();
+
+protected:
+ template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
+ return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
+ }
+
+ using DestructorPtr = void (*)(void *);
+ using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
+ using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
+ CXXDestructorDataPairList DSOHandleOverride;
+ static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
+ void *DSOHandle);
+};
+
+class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
public:
/// Create a runtime-overrides class.
template <typename MangleFtorT>
@@ -159,32 +234,38 @@
return nullptr;
}
- /// Run any destructors recorded by the overriden __cxa_atexit function
- /// (CXAAtExitOverride).
- void runDestructors();
-
private:
- template <typename PtrTy>
- JITTargetAddress toTargetAddress(PtrTy* P) {
- return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
- }
-
void addOverride(const std::string &Name, JITTargetAddress Addr) {
CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
}
StringMap<JITTargetAddress> CXXRuntimeOverrides;
+};
- using DestructorPtr = void (*)(void *);
- using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
- using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
- CXXDestructorDataPairList DSOHandleOverride;
- static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
- void *DSOHandle);
+class LocalCXXRuntimeOverrides2 : public LocalCXXRuntimeOverridesBase {
+public:
+ Error enable(VSO &V, 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.
+class DynamicLibraryFallbackGenerator {
+public:
+ using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+ DynamicLibraryFallbackGenerator(sys::DynamicLibrary Dylib,
+ const DataLayout &DL, SymbolPredicate Allow);
+ SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+
+private:
+ sys::DynamicLibrary Dylib;
+ SymbolPredicate Allow;
+ char GlobalPrefix;
};
} // end namespace orc
-
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
index 8a48c36..a8a88d7 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
@@ -27,7 +27,7 @@
namespace orc {
-/// @brief Global mapping layer.
+/// Global mapping layer.
///
/// This layer overrides the findSymbol method to first search a local symbol
/// table that the client can define. It can be used to inject new symbol
@@ -38,13 +38,13 @@
class GlobalMappingLayer {
public:
- /// @brief Handle to an added module.
+ /// Handle to an added module.
using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
- /// @brief Construct an GlobalMappingLayer with the given BaseLayer
+ /// Construct an GlobalMappingLayer with the given BaseLayer
GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
- /// @brief Add the given module to the JIT.
+ /// Add the given module to the JIT.
/// @return A handle for the added modules.
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
@@ -52,20 +52,20 @@
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
- /// @brief Remove the module set associated with the handle H.
+ /// Remove the module set associated with the handle H.
Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
- /// @brief Manually set the address to return for the given symbol.
+ /// Manually set the address to return for the given symbol.
void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
SymbolTable[Name] = Addr;
}
- /// @brief Remove the given symbol from the global mapping.
+ /// Remove the given symbol from the global mapping.
void eraseGlobalMapping(const std::string &Name) {
SymbolTable.erase(Name);
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
///
/// This method will first search the local symbol table, returning
/// any symbol found there. If the symbol is not found in the local
@@ -81,7 +81,7 @@
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in the context of the of the
+ /// Get the address of the given symbol in the context of the of the
/// module represented by the handle H. This call is forwarded to the
/// base layer's implementation.
/// @param H The handle for the module to search in.
@@ -94,7 +94,7 @@
return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the module set represented by the
+ /// Immediately emit and finalize the module set represented by the
/// given handle.
/// @param H Handle for module set to emit/finalize.
Error emitAndFinalize(ModuleHandleT H) {
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index a7f9416..ad64815 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -16,8 +16,9 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
#include <memory>
#include <string>
@@ -27,7 +28,30 @@
namespace orc {
-/// @brief Eager IR compiling layer.
+class IRCompileLayer2 : public IRLayer {
+public:
+ using CompileFunction =
+ std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>;
+
+ using NotifyCompiledFunction =
+ std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
+
+ IRCompileLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
+ CompileFunction Compile);
+
+ void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled);
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) override;
+
+private:
+ mutable std::mutex IRLayerMutex;
+ ObjectLayer &BaseLayer;
+ CompileFunction Compile;
+ NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
+};
+
+/// Eager IR compiling layer.
///
/// This layer immediately compiles each IR module added via addModule to an
/// object file and adds this module file to the layer below, which must
@@ -35,11 +59,11 @@
template <typename BaseLayerT, typename CompileFtor>
class IRCompileLayer {
public:
- /// @brief Callback type for notifications when modules are compiled.
+ /// Callback type for notifications when modules are compiled.
using NotifyCompiledCallback =
std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
- /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
+ /// Construct an IRCompileLayer with the given BaseLayer, which must
/// implement the ObjectLayer concept.
IRCompileLayer(
BaseLayerT &BaseLayer, CompileFtor Compile,
@@ -47,15 +71,15 @@
: BaseLayer(BaseLayer), Compile(std::move(Compile)),
NotifyCompiled(std::move(NotifyCompiled)) {}
- /// @brief Get a reference to the compiler functor.
+ /// Get a reference to the compiler functor.
CompileFtor& getCompiler() { return Compile; }
- /// @brief (Re)set the NotifyCompiled callback.
+ /// (Re)set the NotifyCompiled callback.
void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) {
this->NotifyCompiled = std::move(NotifyCompiled);
}
- /// @brief Compile the module, and add the resulting object to the base layer
+ /// Compile the module, and add the resulting object to the base layer
/// along with the given memory manager and symbol resolver.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
if (auto Err = BaseLayer.addObject(std::move(K), Compile(*M)))
@@ -65,10 +89,10 @@
return Error::success();
}
- /// @brief Remove the module associated with the VModuleKey K.
+ /// Remove the module associated with the VModuleKey K.
Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); }
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
@@ -76,7 +100,7 @@
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in compiled module represented
+ /// Get the address of the given symbol in compiled module represented
/// by the handle H. This call is forwarded to the base layer's
/// implementation.
/// @param K The VModuleKey for the module to search in.
@@ -89,7 +113,7 @@
return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the module represented by the given
+ /// Immediately emit and finalize the module represented by the given
/// handle.
/// @param K The VModuleKey for the module to emit/finalize.
Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
index 4f1fe7b..266a0f4 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -15,7 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <memory>
#include <string>
@@ -23,7 +23,32 @@
class Module;
namespace orc {
-/// @brief IR mutating layer.
+class IRTransformLayer2 : public IRLayer {
+public:
+
+ using TransformFunction =
+ std::function<Expected<std::unique_ptr<Module>>(std::unique_ptr<Module>)>;
+
+ IRTransformLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
+ TransformFunction Transform = identityTransform);
+
+ void setTransform(TransformFunction Transform) {
+ this->Transform = std::move(Transform);
+ }
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) override;
+
+ static std::unique_ptr<Module> identityTransform(std::unique_ptr<Module> M) {
+ return M;
+ }
+
+private:
+ IRLayer &BaseLayer;
+ TransformFunction Transform;
+};
+
+/// IR mutating layer.
///
/// This layer applies a user supplied transform to each module that is added,
/// then adds the transformed module to the layer below.
@@ -31,12 +56,12 @@
class IRTransformLayer {
public:
- /// @brief Construct an IRTransformLayer with the given BaseLayer
+ /// Construct an IRTransformLayer with the given BaseLayer
IRTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
- /// @brief Apply the transform functor to the module, then add the module to
+ /// Apply the transform functor to the module, then add the module to
/// the layer below, along with the memory manager and symbol resolver.
///
/// @return A handle for the added modules.
@@ -44,10 +69,10 @@
return BaseLayer.addModule(std::move(K), Transform(std::move(M)));
}
- /// @brief Remove the module associated with the VModuleKey K.
+ /// Remove the module associated with the VModuleKey K.
Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); }
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
@@ -55,7 +80,7 @@
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in the context of the module
+ /// Get the address of the given symbol in the context of the module
/// represented by the VModuleKey K. This call is forwarded to the base
/// layer's implementation.
/// @param K The VModuleKey for the module to search in.
@@ -68,15 +93,15 @@
return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the module represented by the given
+ /// Immediately emit and finalize the module represented by the given
/// VModuleKey.
/// @param K The VModuleKey for the module to emit/finalize.
Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
- /// @brief Access the transform functor directly.
+ /// Access the transform functor directly.
TransformFtor& getTransform() { return Transform; }
- /// @brief Access the mumate functor directly.
+ /// Access the mumate functor directly.
const TransformFtor& getTransform() const { return Transform; }
private:
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index 029b86a..8b0b3fd 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Process.h"
@@ -46,98 +47,29 @@
namespace orc {
-/// @brief Target-independent base class for compile callback management.
+/// Target-independent base class for compile callback management.
class JITCompileCallbackManager {
public:
- using CompileFtor = std::function<JITTargetAddress()>;
+ using CompileFunction = std::function<JITTargetAddress()>;
- /// @brief Handle to a newly created compile callback. Can be used to get an
- /// IR constant representing the address of the trampoline, and to set
- /// the compile action for the callback.
- class CompileCallbackInfo {
- public:
- CompileCallbackInfo(JITTargetAddress Addr, CompileFtor &Compile)
- : Addr(Addr), Compile(Compile) {}
-
- JITTargetAddress getAddress() const { return Addr; }
- void setCompileAction(CompileFtor Compile) {
- this->Compile = std::move(Compile);
- }
-
- private:
- JITTargetAddress Addr;
- CompileFtor &Compile;
- };
-
- /// @brief Construct a JITCompileCallbackManager.
+ /// Construct a JITCompileCallbackManager.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
- JITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
- : ErrorHandlerAddress(ErrorHandlerAddress) {}
+ JITCompileCallbackManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : ES(ES), CallbacksVSO(ES.createVSO("<Callbacks>")),
+ ErrorHandlerAddress(ErrorHandlerAddress) {}
virtual ~JITCompileCallbackManager() = default;
- /// @brief Execute the callback for the given trampoline id. Called by the JIT
+ /// 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) {
- auto I = ActiveTrampolines.find(TrampolineAddr);
- // FIXME: Also raise an error in the Orc error-handler when we finally have
- // one.
- if (I == ActiveTrampolines.end())
- return ErrorHandlerAddress;
-
- // Found a callback handler. Yank this trampoline out of the active list and
- // put it back in the available trampolines list, then try to run the
- // handler's compile and update actions.
- // Moving the trampoline ID back to the available list first means there's
- // at
- // least one available trampoline if the compile action triggers a request
- // for
- // a new one.
- auto Compile = std::move(I->second);
- ActiveTrampolines.erase(I);
- AvailableTrampolines.push_back(TrampolineAddr);
-
- if (auto Addr = Compile())
- return Addr;
-
- return ErrorHandlerAddress;
- }
-
- /// @brief Reserve a compile callback.
- Expected<CompileCallbackInfo> getCompileCallback() {
- if (auto TrampolineAddrOrErr = getAvailableTrampolineAddr()) {
- const auto &TrampolineAddr = *TrampolineAddrOrErr;
- auto &Compile = this->ActiveTrampolines[TrampolineAddr];
- return CompileCallbackInfo(TrampolineAddr, Compile);
- } else
- return TrampolineAddrOrErr.takeError();
- }
-
- /// @brief Get a CompileCallbackInfo for an existing callback.
- CompileCallbackInfo getCompileCallbackInfo(JITTargetAddress TrampolineAddr) {
- auto I = ActiveTrampolines.find(TrampolineAddr);
- assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
- return CompileCallbackInfo(I->first, I->second);
- }
-
- /// @brief Release a compile callback.
- ///
- /// Note: Callbacks are auto-released after they execute. This method should
- /// only be called to manually release a callback that is not going to
- /// execute.
- void releaseCompileCallback(JITTargetAddress TrampolineAddr) {
- auto I = ActiveTrampolines.find(TrampolineAddr);
- assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
- ActiveTrampolines.erase(I);
- AvailableTrampolines.push_back(TrampolineAddr);
- }
+ JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
protected:
- JITTargetAddress ErrorHandlerAddress;
-
- using TrampolineMapT = std::map<JITTargetAddress, CompileFtor>;
- TrampolineMapT ActiveTrampolines;
std::vector<JITTargetAddress> AvailableTrampolines;
private:
@@ -156,17 +88,25 @@
virtual Error grow() = 0;
virtual void anchor();
+
+ std::mutex CCMgrMutex;
+ ExecutionSession &ES;
+ VSO &CallbacksVSO;
+ JITTargetAddress ErrorHandlerAddress;
+ std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
+ size_t NextCallbackId = 0;
};
-/// @brief Manage compile callbacks for in-process JITs.
+/// Manage compile callbacks for in-process JITs.
template <typename TargetT>
class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
public:
- /// @brief Construct a InProcessJITCompileCallbackManager.
+ /// Construct a InProcessJITCompileCallbackManager.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
- LocalJITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ErrorHandlerAddress) {
+ LocalJITCompileCallbackManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : JITCompileCallbackManager(ES, ErrorHandlerAddress) {
/// Set up the resolver block.
std::error_code EC;
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
@@ -229,38 +169,38 @@
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
};
-/// @brief Base class for managing collections of named indirect stubs.
+/// Base class for managing collections of named indirect stubs.
class IndirectStubsManager {
public:
- /// @brief Map type for initializing the manager. See init.
+ /// Map type for initializing the manager. See init.
using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>;
virtual ~IndirectStubsManager() = default;
- /// @brief Create a single stub with the given name, target address and flags.
+ /// Create a single stub with the given name, target address and flags.
virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr,
JITSymbolFlags StubFlags) = 0;
- /// @brief Create StubInits.size() stubs with the given names, target
+ /// Create StubInits.size() stubs with the given names, target
/// addresses, and flags.
virtual Error createStubs(const StubInitsMap &StubInits) = 0;
- /// @brief Find the stub with the given name. If ExportedStubsOnly is true,
+ /// Find the stub with the given name. If ExportedStubsOnly is true,
/// this will only return a result if the stub's flags indicate that it
/// is exported.
- virtual JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
+ virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
- /// @brief Find the implementation-pointer for the stub.
- virtual JITSymbol findPointer(StringRef Name) = 0;
+ /// Find the implementation-pointer for the stub.
+ virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0;
- /// @brief Change the value of the implementation pointer for the stub.
+ /// Change the value of the implementation pointer for the stub.
virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0;
private:
virtual void anchor();
};
-/// @brief IndirectStubsManager implementation for the host architecture, e.g.
+/// IndirectStubsManager implementation for the host architecture, e.g.
/// OrcX86_64. (See OrcArchitectureSupport.h).
template <typename TargetT>
class LocalIndirectStubsManager : public IndirectStubsManager {
@@ -286,7 +226,7 @@
return Error::success();
}
- JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+ JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
@@ -295,13 +235,13 @@
assert(StubAddr && "Missing stub address");
auto StubTargetAddr =
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
- auto StubSymbol = JITSymbol(StubTargetAddr, I->second.second);
+ auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second);
if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
return nullptr;
return StubSymbol;
}
- JITSymbol findPointer(StringRef Name) override {
+ JITEvaluatedSymbol findPointer(StringRef Name) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
@@ -310,7 +250,7 @@
assert(PtrAddr && "Missing pointer address");
auto PtrTargetAddr =
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
- return JITSymbol(PtrTargetAddr, I->second.second);
+ return JITEvaluatedSymbol(PtrTargetAddr, I->second.second);
}
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
@@ -354,45 +294,45 @@
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
};
-/// @brief Create a local compile callback manager.
+/// Create a local compile callback manager.
///
/// 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>
-createLocalCompileCallbackManager(const Triple &T,
+createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress);
-/// @brief Create a local indriect stubs manager builder.
+/// Create a local indriect stubs manager builder.
///
/// The given target triple will determine the ABI.
std::function<std::unique_ptr<IndirectStubsManager>()>
createLocalIndirectStubsManagerBuilder(const Triple &T);
-/// @brief Build a function pointer of FunctionType with the given constant
+/// Build a function pointer of FunctionType with the given constant
/// address.
///
/// Usage example: Turn a trampoline address into a function pointer constant
/// for use in a stub.
Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr);
-/// @brief Create a function pointer with the given type, name, and initializer
+/// Create a function pointer with the given type, name, and initializer
/// in the given Module.
GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
Constant *Initializer);
-/// @brief Turn a function declaration into a stub function that makes an
+/// Turn a function declaration into a stub function that makes an
/// indirect call using the given function pointer.
void makeStub(Function &F, Value &ImplPointer);
-/// @brief Raise linkage types and rename as necessary to ensure that all
+/// 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);
-/// @brief Clone a function declaration into a new module.
+/// Clone a function declaration into a new module.
///
/// This function can be used as the first step towards creating a callback
/// stub (see makeStub), or moving a function body (see moveFunctionBody).
@@ -407,7 +347,7 @@
Function *cloneFunctionDecl(Module &Dst, const Function &F,
ValueToValueMapTy *VMap = nullptr);
-/// @brief Move the body of function 'F' to a cloned function declaration in a
+/// Move the body of function 'F' to a cloned function declaration in a
/// different module (See related cloneFunctionDecl).
///
/// If the target function declaration is not supplied via the NewF parameter
@@ -419,11 +359,11 @@
ValueMaterializer *Materializer = nullptr,
Function *NewF = nullptr);
-/// @brief Clone a global variable declaration into a new module.
+/// Clone a global variable declaration into a new module.
GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
ValueToValueMapTy *VMap = nullptr);
-/// @brief Move global variable GV from its parent module to cloned global
+/// Move global variable GV from its parent module to cloned global
/// declaration in a different module.
///
/// If the target global declaration is not supplied via the NewGV parameter
@@ -436,11 +376,11 @@
ValueMaterializer *Materializer = nullptr,
GlobalVariable *NewGV = nullptr);
-/// @brief Clone a global alias declaration into a new module.
+/// Clone a global alias declaration into a new module.
GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
ValueToValueMapTy &VMap);
-/// @brief Clone module flags metadata into the destination module.
+/// Clone module flags metadata into the destination module.
void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
ValueToValueMapTy &VMap);
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
new file mode 100644
index 0000000..df655bd
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -0,0 +1,143 @@
+//===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for 3Bdetails.
+//
+//===----------------------------------------------------------------------===//
+//
+// An ORC-based JIT for compiling LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+#define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+namespace orc {
+
+/// 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.
+ ExecutionSession &getExecutionSession() { return *ES; }
+
+ /// Returns a reference to the VSO representing the JIT'd main program.
+ VSO &getMainVSO() { 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);
+
+ /// Adds an IR module to the Main VSO.
+ Error addIRModule(std::unique_ptr<Module> M) {
+ return addIRModule(Main, std::move(M));
+ }
+
+ /// 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);
+
+ /// Look up a symbol in the main VSO 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 the main VSO based on its IR symbol name.
+ Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
+ return lookup(Main, UnmangledName);
+ }
+
+ /// Runs all not-yet-run static constructors.
+ Error runConstructors() { return CtorRunner.run(); }
+
+ /// Runs all not-yet-run static destructors.
+ Error runDestructors() { return DtorRunner.run(); }
+
+protected:
+ LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
+ DataLayout DL);
+
+ std::shared_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K);
+
+ std::string mangle(StringRef UnmangledName);
+
+ Error applyDataLayout(Module &M);
+
+ void recordCtorDtors(Module &M);
+
+ std::unique_ptr<ExecutionSession> ES;
+ VSO &Main;
+
+ std::unique_ptr<TargetMachine> TM;
+ DataLayout DL;
+
+ RTDyldObjectLinkingLayer2 ObjLinkingLayer;
+ IRCompileLayer2 CompileLayer;
+
+ CtorDtorRunner2 CtorRunner, DtorRunner;
+};
+
+/// An extended version of LLJIT that supports lazy function-at-a-time
+/// compilation of LLVM IR.
+class LLLazyJIT : public LLJIT {
+public:
+ /// Create an LLLazyJIT instance.
+ static Expected<std::unique_ptr<LLLazyJIT>>
+ Create(std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx);
+
+ /// Set an IR transform (e.g. pass manager pipeline) to run on each function
+ /// when it is compiled.
+ void setLazyCompileTransform(IRTransformLayer2::TransformFunction Transform) {
+ TransformLayer.setTransform(std::move(Transform));
+ }
+
+ /// Add a module to be lazily compiled to VSO V.
+ Error addLazyIRModule(VSO &V, std::unique_ptr<Module> M);
+
+ /// Add a module to be lazily compiled to the main VSO.
+ Error addLazyIRModule(std::unique_ptr<Module> M) {
+ return addLazyIRModule(Main, std::move(M));
+ }
+
+private:
+ LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx,
+ std::unique_ptr<JITCompileCallbackManager> CCMgr,
+ std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
+
+ std::unique_ptr<JITCompileCallbackManager> CCMgr;
+ std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
+
+ IRTransformLayer2 TransformLayer;
+ CompileOnDemandLayer2 CODLayer;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
new file mode 100644
index 0000000..da37266
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -0,0 +1,136 @@
+//===---------------- Layer.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.
+//
+//===----------------------------------------------------------------------===//
+//
+// Layer interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_LAYER_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace llvm {
+namespace orc {
+
+/// Interface for layers that accept LLVM IR.
+class IRLayer {
+public:
+ IRLayer(ExecutionSession &ES);
+ virtual ~IRLayer();
+
+ /// 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);
+
+ /// Emit should materialize the given IR.
+ virtual void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<Module> M) = 0;
+
+private:
+ ExecutionSession &ES;
+};
+
+/// IRMaterializationUnit is a convenient base class for MaterializationUnits
+/// wrapping LLVM IR. Represents materialization responsibility for all symbols
+/// in the given module. If symbols are overridden by other definitions, then
+/// their linkage is changed to available-externally.
+class IRMaterializationUnit : public MaterializationUnit {
+public:
+ using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
+
+ /// Create an IRMaterializationLayer. Scans the module to build the
+ /// SymbolFlags and SymbolToDefinition maps.
+ IRMaterializationUnit(ExecutionSession &ES, std::unique_ptr<Module> M);
+
+ /// 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,
+ SymbolNameToDefinitionMap SymbolToDefinition);
+
+protected:
+ std::unique_ptr<Module> M;
+ SymbolNameToDefinitionMap SymbolToDefinition;
+
+private:
+ void discard(const VSO &V, SymbolStringPtr Name) override;
+};
+
+/// MaterializationUnit that materializes modules by calling the 'emit' method
+/// on the given IRLayer.
+class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
+public:
+ BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K,
+ std::unique_ptr<Module> M);
+private:
+
+ void materialize(MaterializationResponsibility R) override;
+
+ IRLayer &L;
+ VModuleKey K;
+};
+
+/// Interface for Layers that accept object files.
+class ObjectLayer {
+public:
+ ObjectLayer(ExecutionSession &ES);
+ virtual ~ObjectLayer();
+
+ /// 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);
+
+ /// Emit should materialize the given IR.
+ virtual void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O) = 0;
+
+private:
+ ExecutionSession &ES;
+};
+
+/// Materializes the given object file (represented by a MemoryBuffer
+/// instance) by calling 'emit' on the given ObjectLayer.
+class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
+public:
+ static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
+ Create(ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+
+ BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O,
+ SymbolFlagsMap SymbolFlags);
+
+private:
+
+ void materialize(MaterializationResponsibility R) override;
+ void discard(const VSO &V, SymbolStringPtr Name) override;
+
+ ObjectLayer &L;
+ VModuleKey K;
+ std::unique_ptr<MemoryBuffer> O;
+};
+
+/// Returns a SymbolFlagsMap for the object file represented by the given
+/// buffer, or an error if the buffer does not contain a valid object file.
+// FIXME: Maybe move to Core.h?
+Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES,
+ MemoryBufferRef ObjBuffer);
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
index 4117a92..46761b0 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -33,7 +33,7 @@
namespace llvm {
namespace orc {
-/// @brief Lazy-emitting IR layer.
+/// Lazy-emitting IR layer.
///
/// This layer accepts LLVM IR Modules (via addModule), but does not
/// immediately emit them the layer below. Instead, emissing to the base layer
@@ -196,10 +196,10 @@
public:
- /// @brief Construct a lazy emitting layer.
+ /// Construct a lazy emitting layer.
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
- /// @brief Add the given module to the lazy emitting layer.
+ /// Add the given module to the lazy emitting layer.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
assert(!ModuleMap.count(K) && "VModuleKey K already in use");
ModuleMap[K] =
@@ -207,7 +207,7 @@
return Error::success();
}
- /// @brief Remove the module represented by the given handle.
+ /// Remove the module represented by the given handle.
///
/// This method will free the memory associated with the given module, both
/// in this layer, and the base layer.
@@ -219,7 +219,7 @@
return EDM->removeModuleFromBaseLayer(BaseLayer);
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
@@ -239,7 +239,7 @@
return nullptr;
}
- /// @brief Get the address of the given symbol in the context of the of
+ /// Get the address of the given symbol in the context of the of
/// compiled modules represented by the key K.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
@@ -247,7 +247,7 @@
return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
}
- /// @brief Immediately emit and finalize the module represented by the given
+ /// Immediately emit and finalize the module represented by the given
/// key.
Error emitAndFinalize(VModuleKey K) {
assert(ModuleMap.count(K) && "VModuleKey K not valid here");
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
index b2b389a..52c8c16 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
@@ -20,9 +20,76 @@
namespace llvm {
namespace orc {
+/// SymbolResolver is a composable interface for looking up symbol flags
+/// and addresses using the AsynchronousSymbolQuery type. It will
+/// eventually replace the LegacyJITSymbolResolver interface as the
+/// stardard ORC symbol resolver type.
+///
+/// FIXME: SymbolResolvers should go away and be replaced with VSOs with
+/// defenition generators.
+class SymbolResolver {
+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;
+
+ /// 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.
+ virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) = 0;
+
+private:
+ virtual void anchor();
+};
+
+/// Implements SymbolResolver with a pair of supplied function objects
+/// for convenience. See createSymbolResolver.
+template <typename LookupFlagsFn, typename LookupFn>
+class LambdaSymbolResolver final : public SymbolResolver {
+public:
+ template <typename LookupFlagsFnRef, typename LookupFnRef>
+ LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
+ : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
+ Lookup(std::forward<LookupFnRef>(Lookup)) {}
+
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
+ return LookupFlags(Symbols);
+ }
+
+ SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+ SymbolNameSet Symbols) final {
+ return Lookup(std::move(Query), std::move(Symbols));
+ }
+
+private:
+ LookupFlagsFn LookupFlags;
+ LookupFn Lookup;
+};
+
+/// Creates a SymbolResolver implementation from the pair of supplied
+/// function objects.
+template <typename LookupFlagsFn, typename LookupFn>
+std::unique_ptr<LambdaSymbolResolver<
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFn>::type>::type>>
+createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
+ using LambdaSymbolResolverImpl = LambdaSymbolResolver<
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFlagsFn>::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));
+}
+
class JITSymbolResolverAdapter : public JITSymbolResolver {
public:
- JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R);
+ JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
+ MaterializationResponsibility *MR);
Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
Expected<LookupResult> lookup(const LookupSet &Symbols) override;
@@ -30,9 +97,10 @@
ExecutionSession &ES;
std::set<SymbolStringPtr> ResolvedStrings;
SymbolResolver &R;
+ MaterializationResponsibility *MR;
};
-/// @brief Use the given legacy-style FindSymbol function (i.e. a function that
+/// 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
@@ -41,95 +109,100 @@
///
/// Useful for implementing lookupFlags bodies that query legacy resolvers.
template <typename FindSymbolFn>
-Expected<SymbolNameSet> lookupFlagsWithLegacyFn(SymbolFlagsMap &SymbolFlags,
- const SymbolNameSet &Symbols,
- FindSymbolFn FindSymbol) {
- SymbolNameSet SymbolsNotFound;
+Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols,
+ FindSymbolFn FindSymbol) {
+ SymbolFlagsMap SymbolFlags;
for (auto &S : Symbols) {
if (JITSymbol Sym = FindSymbol(*S))
SymbolFlags[S] = Sym.getFlags();
else if (auto Err = Sym.takeError())
return std::move(Err);
- else
- SymbolsNotFound.insert(S);
}
- return SymbolsNotFound;
+ return SymbolFlags;
}
-/// @brief Use the given legacy-style FindSymbol function (i.e. a function that
+/// 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 address and flags for each symbol in Symbols and store the
/// result in Query. If any JITSymbol returned by FindSymbol is in an
-/// error then Query.setFailed(...) is called with that error and the
+/// error then Query.notifyFailed(...) is called with that error and the
/// function returns immediately. On success, returns the set of symbols
/// not found.
///
/// Useful for implementing lookup bodies that query legacy resolvers.
template <typename FindSymbolFn>
-SymbolNameSet lookupWithLegacyFn(AsynchronousSymbolQuery &Query,
- const SymbolNameSet &Symbols,
- FindSymbolFn FindSymbol) {
+SymbolNameSet
+lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
+ const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
SymbolNameSet SymbolsNotFound;
+ bool NewSymbolsResolved = false;
for (auto &S : Symbols) {
if (JITSymbol Sym = FindSymbol(*S)) {
if (auto Addr = Sym.getAddress()) {
- Query.setDefinition(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
- Query.notifySymbolFinalized();
+ Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
+ Query.notifySymbolReady();
+ NewSymbolsResolved = true;
} else {
- Query.setFailed(Addr.takeError());
+ ES.legacyFailQuery(Query, Addr.takeError());
return SymbolNameSet();
}
} else if (auto Err = Sym.takeError()) {
- Query.setFailed(std::move(Err));
+ ES.legacyFailQuery(Query, std::move(Err));
return SymbolNameSet();
} else
SymbolsNotFound.insert(S);
}
+ if (NewSymbolsResolved && Query.isFullyResolved())
+ Query.handleFullyResolved();
+
+ if (NewSymbolsResolved && Query.isFullyReady())
+ Query.handleFullyReady();
+
return SymbolsNotFound;
}
-/// @brief An ORC SymbolResolver implementation that uses a legacy
+/// An ORC SymbolResolver implementation that uses a legacy
/// findSymbol-like function to perform lookup;
template <typename LegacyLookupFn>
class LegacyLookupFnResolver final : public SymbolResolver {
public:
using ErrorReporter = std::function<void(Error)>;
- LegacyLookupFnResolver(LegacyLookupFn LegacyLookup, ErrorReporter ReportError)
- : LegacyLookup(std::move(LegacyLookup)),
+ LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
+ ErrorReporter ReportError)
+ : ES(ES), LegacyLookup(std::move(LegacyLookup)),
ReportError(std::move(ReportError)) {}
- SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
- const SymbolNameSet &Symbols) final {
- if (auto RemainingSymbols =
- lookupFlagsWithLegacyFn(Flags, Symbols, LegacyLookup))
- return std::move(*RemainingSymbols);
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
+ if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup))
+ return std::move(*SymbolFlags);
else {
- ReportError(RemainingSymbols.takeError());
- return Symbols;
+ ReportError(SymbolFlags.takeError());
+ return SymbolFlagsMap();
}
}
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) final {
- return lookupWithLegacyFn(*Query, Symbols, LegacyLookup);
+ return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
}
private:
+ ExecutionSession &ES;
LegacyLookupFn LegacyLookup;
ErrorReporter ReportError;
};
template <typename LegacyLookupFn>
std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
-createLegacyLookupResolver(LegacyLookupFn LegacyLookup,
+createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
std::function<void(Error)> ErrorReporter) {
return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
- std::move(LegacyLookup), std::move(ErrorReporter));
+ ES, std::move(LegacyLookup), std::move(ErrorReporter));
}
} // End namespace orc
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
index eba9b95..3dd3cfe 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
@@ -15,7 +15,7 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
namespace llvm {
@@ -23,8 +23,7 @@
class NullResolver : public SymbolResolver {
public:
- SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
- const SymbolNameSet &Symbols) override;
+ SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) override;
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) override;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
index cfc3922..c6b43a9 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
@@ -15,7 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <algorithm>
#include <memory>
#include <string>
@@ -23,7 +23,24 @@
namespace llvm {
namespace orc {
-/// @brief Object mutating layer.
+class ObjectTransformLayer2 : public ObjectLayer {
+public:
+ using TransformFunction =
+ std::function<Expected<std::unique_ptr<MemoryBuffer>>(
+ std::unique_ptr<MemoryBuffer>)>;
+
+ ObjectTransformLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
+ TransformFunction Transform);
+
+ void emit(MaterializationResponsibility R, VModuleKey K,
+ std::unique_ptr<MemoryBuffer> O) override;
+
+private:
+ ObjectLayer &BaseLayer;
+ TransformFunction Transform;
+};
+
+/// Object mutating layer.
///
/// This layer accepts sets of ObjectFiles (via addObject). It
/// immediately applies the user supplied functor to each object, then adds
@@ -31,12 +48,12 @@
template <typename BaseLayerT, typename TransformFtor>
class ObjectTransformLayer {
public:
- /// @brief Construct an ObjectTransformLayer with the given BaseLayer
+ /// Construct an ObjectTransformLayer with the given BaseLayer
ObjectTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
- /// @brief Apply the transform functor to each object in the object set, then
+ /// Apply the transform functor to each object in the object set, then
/// add the resulting set of objects to the base layer, along with the
/// memory manager and symbol resolver.
///
@@ -45,10 +62,10 @@
return BaseLayer.addObject(std::move(K), Transform(std::move(Obj)));
}
- /// @brief Remove the object set associated with the VModuleKey K.
+ /// Remove the object set associated with the VModuleKey K.
Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); }
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
@@ -56,7 +73,7 @@
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Get the address of the given symbol in the context of the set of
+ /// Get the address of the given symbol in the context of the set of
/// objects represented by the VModuleKey K. This call is forwarded to
/// the base layer's implementation.
/// @param K The VModuleKey associated with the object set to search in.
@@ -69,21 +86,21 @@
return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
- /// @brief Immediately emit and finalize the object set represented by the
+ /// Immediately emit and finalize the object set represented by the
/// given VModuleKey K.
Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
- /// @brief Map section addresses for the objects associated with the
+ /// Map section addresses for the objects associated with the
/// VModuleKey K.
void mapSectionAddress(VModuleKey K, const void *LocalAddress,
JITTargetAddress TargetAddr) {
BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr);
}
- /// @brief Access the transform functor directly.
+ /// Access the transform functor directly.
TransformFtor &getTransform() { return Transform; }
- /// @brief Access the mumate functor directly.
+ /// Access the mumate functor directly.
const TransformFtor &getTransform() const { return Transform; }
private:
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
index e1b5564..581c598 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
@@ -71,7 +71,7 @@
}
};
-/// @brief Provide information about stub blocks generated by the
+/// Provide information about stub blocks generated by the
/// makeIndirectStubsBlock function.
template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
public:
@@ -92,16 +92,16 @@
return *this;
}
- /// @brief Number of stubs in this block.
+ /// Number of stubs in this block.
unsigned getNumStubs() const { return NumStubs; }
- /// @brief Get a pointer to the stub at the given index, which must be in
+ /// Get a pointer to the stub at the given index, which must be in
/// the range 0 .. getNumStubs() - 1.
void *getStub(unsigned Idx) const {
return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
}
- /// @brief Get a pointer to the implementation-pointer at the given index,
+ /// Get a pointer to the implementation-pointer at the given index,
/// which must be in the range 0 .. getNumStubs() - 1.
void **getPtr(unsigned Idx) const {
char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
@@ -124,18 +124,18 @@
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// 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,
+ /// 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
+ /// Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
@@ -145,7 +145,7 @@
unsigned MinStubs, void *InitialPtrVal);
};
-/// @brief X86_64 code that's common to all ABIs.
+/// X86_64 code that's common to all ABIs.
///
/// X86_64 supports lazy JITing.
class OrcX86_64_Base {
@@ -155,13 +155,13 @@
using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
- /// @brief Write the requsted number of trampolines into the given memory,
+ /// 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
+ /// Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
@@ -171,7 +171,7 @@
unsigned MinStubs, void *InitialPtrVal);
};
-/// @brief X86_64 support for SysV ABI (Linux, MacOSX).
+/// X86_64 support for SysV ABI (Linux, MacOSX).
///
/// X86_64_SysV supports lazy JITing.
class OrcX86_64_SysV : public OrcX86_64_Base {
@@ -181,13 +181,13 @@
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// 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 X86_64 support for Win32.
+/// X86_64 support for Win32.
///
/// X86_64_Win32 supports lazy JITing.
class OrcX86_64_Win32 : public OrcX86_64_Base {
@@ -197,13 +197,13 @@
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// 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 I386 support.
+/// I386 support.
///
/// I386 supports lazy JITing.
class OrcI386 {
@@ -217,18 +217,18 @@
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
+ /// 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,
+ /// 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
+ /// Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
index c2ff41e..dc60e8d 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -22,7 +22,8 @@
enum class OrcErrorCode : int {
// RPC Errors
- DuplicateDefinition = 1,
+ UnknownORCError = 1,
+ DuplicateDefinition,
JITSymbolNotFound,
RemoteAllocatorDoesNotExist,
RemoteAllocatorIdAlreadyInUse,
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 7179e5f..739e5ba 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -63,7 +63,7 @@
public:
~RemoteRTDyldMemoryManager() {
Client.destroyRemoteAllocator(Id);
- DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
}
RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
@@ -79,9 +79,9 @@
Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
uint8_t *Alloc = reinterpret_cast<uint8_t *>(
Unmapped.back().CodeAllocs.back().getLocalAddress());
- DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
- << SectionName << ": " << Alloc << " (" << Size
- << " bytes, alignment " << Alignment << ")\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
+ << SectionName << ": " << Alloc << " (" << Size
+ << " bytes, alignment " << Alignment << ")\n");
return Alloc;
}
@@ -92,18 +92,18 @@
Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
uint8_t *Alloc = reinterpret_cast<uint8_t *>(
Unmapped.back().RODataAllocs.back().getLocalAddress());
- DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
- << SectionName << ": " << Alloc << " (" << Size
- << " bytes, alignment " << Alignment << ")\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
+ << SectionName << ": " << Alloc << " (" << Size
+ << " bytes, alignment " << Alignment << ")\n");
return Alloc;
} // else...
Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
uint8_t *Alloc = reinterpret_cast<uint8_t *>(
Unmapped.back().RWDataAllocs.back().getLocalAddress());
- DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
- << SectionName << ": " << Alloc << " (" << Size
- << " bytes, alignment " << Alignment << ")\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
+ << SectionName << ": " << Alloc << " (" << Size
+ << " bytes, alignment " << Alignment << ")\n");
return Alloc;
}
@@ -113,36 +113,36 @@
uint32_t RWDataAlign) override {
Unmapped.push_back(ObjectAllocs());
- DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
if (CodeSize != 0) {
Unmapped.back().RemoteCodeAddr =
Client.reserveMem(Id, CodeSize, CodeAlign);
- DEBUG(dbgs() << " code: "
- << format("0x%016x", Unmapped.back().RemoteCodeAddr)
- << " (" << CodeSize << " bytes, alignment " << CodeAlign
- << ")\n");
+ LLVM_DEBUG(dbgs() << " code: "
+ << format("0x%016x", Unmapped.back().RemoteCodeAddr)
+ << " (" << CodeSize << " bytes, alignment "
+ << CodeAlign << ")\n");
}
if (RODataSize != 0) {
Unmapped.back().RemoteRODataAddr =
Client.reserveMem(Id, RODataSize, RODataAlign);
- DEBUG(dbgs() << " ro-data: "
- << format("0x%016x", Unmapped.back().RemoteRODataAddr)
- << " (" << RODataSize << " bytes, alignment "
- << RODataAlign << ")\n");
+ LLVM_DEBUG(dbgs() << " ro-data: "
+ << format("0x%016x", Unmapped.back().RemoteRODataAddr)
+ << " (" << RODataSize << " bytes, alignment "
+ << RODataAlign << ")\n");
}
if (RWDataSize != 0) {
Unmapped.back().RemoteRWDataAddr =
Client.reserveMem(Id, RWDataSize, RWDataAlign);
- DEBUG(dbgs() << " rw-data: "
- << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
- << " (" << RWDataSize << " bytes, alignment "
- << RWDataAlign << ")\n");
+ LLVM_DEBUG(dbgs() << " rw-data: "
+ << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
+ << " (" << RWDataSize << " bytes, alignment "
+ << RWDataAlign << ")\n");
}
}
@@ -162,7 +162,7 @@
void notifyObjectLoaded(RuntimeDyld &Dyld,
const object::ObjectFile &Obj) override {
- DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
for (auto &ObjAllocs : Unmapped) {
mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
ObjAllocs.RemoteCodeAddr);
@@ -176,7 +176,7 @@
}
bool finalizeMemory(std::string *ErrMsg = nullptr) override {
- DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
+ LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
for (auto &ObjAllocs : Unfinalized) {
if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
@@ -261,7 +261,7 @@
RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
ResourceIdMgr::ResourceId Id)
: Client(Client), Id(Id) {
- DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
}
// Maps all allocations in Allocs to aligned blocks
@@ -270,8 +270,9 @@
for (auto &Alloc : Allocs) {
NextAddr = alignTo(NextAddr, Alloc.getAlign());
Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
- DEBUG(dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())
- << " -> " << format("0x%016x", NextAddr) << "\n");
+ LLVM_DEBUG(dbgs() << " "
+ << static_cast<void *>(Alloc.getLocalAddress())
+ << " -> " << format("0x%016x", NextAddr) << "\n");
Alloc.setRemoteAddress(NextAddr);
// Only advance NextAddr if it was non-null to begin with,
@@ -290,22 +291,23 @@
assert(!Allocs.empty() && "No sections in allocated segment");
for (auto &Alloc : Allocs) {
- DEBUG(dbgs() << " copying section: "
- << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
- << format("0x%016x", Alloc.getRemoteAddress()) << " ("
- << Alloc.getSize() << " bytes)\n";);
+ LLVM_DEBUG(dbgs() << " copying section: "
+ << static_cast<void *>(Alloc.getLocalAddress())
+ << " -> "
+ << format("0x%016x", Alloc.getRemoteAddress())
+ << " (" << Alloc.getSize() << " bytes)\n";);
if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
Alloc.getSize()))
return true;
}
- DEBUG(dbgs() << " setting "
- << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
- << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
- << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
- << " permissions on block: "
- << format("0x%016x", RemoteSegmentAddr) << "\n");
+ LLVM_DEBUG(dbgs() << " setting "
+ << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
+ << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
+ << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
+ << " permissions on block: "
+ << format("0x%016x", RemoteSegmentAddr) << "\n");
if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
return true;
}
@@ -356,25 +358,25 @@
return Error::success();
}
- JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+ JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
auto Key = I->second.first;
auto Flags = I->second.second;
- auto StubSymbol = JITSymbol(getStubAddr(Key), Flags);
+ auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
return nullptr;
return StubSymbol;
}
- JITSymbol findPointer(StringRef Name) override {
+ JITEvaluatedSymbol findPointer(StringRef Name) override {
auto I = StubIndexes.find(Name);
if (I == StubIndexes.end())
return nullptr;
auto Key = I->second.first;
auto Flags = I->second.second;
- return JITSymbol(getPtrAddr(Key), Flags);
+ return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
}
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
@@ -449,8 +451,9 @@
class RemoteCompileCallbackManager : public JITCompileCallbackManager {
public:
RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
+ ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
+ : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
private:
Error grow() override {
@@ -475,10 +478,10 @@
/// Channel is the ChannelT instance to communicate on. It is assumed that
/// the channel is ready to be read from and written to.
static Expected<std::unique_ptr<OrcRemoteTargetClient>>
- Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) {
+ Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
Error Err = Error::success();
auto Client = std::unique_ptr<OrcRemoteTargetClient>(
- new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
+ new OrcRemoteTargetClient(Channel, ES, Err));
if (Err)
return std::move(Err);
return std::move(Client);
@@ -487,7 +490,8 @@
/// Call the int(void) function at the given address in the target and return
/// its result.
Expected<int> callIntVoid(JITTargetAddress Addr) {
- DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr)
+ << "\n");
return callB<exec::CallIntVoid>(Addr);
}
@@ -495,16 +499,16 @@
/// return its result.
Expected<int> callMain(JITTargetAddress Addr,
const std::vector<std::string> &Args) {
- DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
- << "\n");
+ LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
+ << format("0x%016x", Addr) << "\n");
return callB<exec::CallMain>(Addr, Args);
}
/// Call the void() function at the given address in the target and wait for
/// it to finish.
Error callVoidVoid(JITTargetAddress Addr) {
- DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
- << "\n");
+ LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
+ << "\n");
return callB<exec::CallVoidVoid>(Addr);
}
@@ -531,12 +535,14 @@
Expected<RemoteCompileCallbackManager &>
enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
+ assert(!CallbackManager && "CallbackManager already obtained");
+
// Emit the resolver block on the JIT server.
if (auto Err = callB<stubs::EmitResolverBlock>())
return std::move(Err);
// Create the callback manager.
- CallbackManager.emplace(*this, ErrorHandlerAddress);
+ CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
RemoteCompileCallbackManager &Mgr = *CallbackManager;
return Mgr;
}
@@ -554,10 +560,10 @@
Error terminateSession() { return callB<utils::TerminateSession>(); }
private:
- OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
- std::function<void(Error)> ReportError, Error &Err)
+ OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
+ Error &Err)
: rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
- ReportError(std::move(ReportError)) {
+ ES(ES) {
ErrorAsOutParameter EAO(&Err);
addHandler<utils::RequestCompile>(
@@ -577,7 +583,7 @@
void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
}
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
@@ -592,7 +598,7 @@
void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
IndirectStubOwnerIds.release(Id);
if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
}
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
@@ -625,7 +631,7 @@
if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
return *AddrOrErr;
else {
- ReportError(AddrOrErr.takeError());
+ ES.reportError(AddrOrErr.takeError());
return 0;
}
}
@@ -633,7 +639,7 @@
bool setProtections(ResourceIdMgr::ResourceId Id,
JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
return true;
} else
return false;
@@ -641,7 +647,7 @@
bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
- ReportError(std::move(Err));
+ ES.reportError(std::move(Err));
return true;
} else
return false;
@@ -653,6 +659,7 @@
static Error doNothing() { return Error::success(); }
+ ExecutionSession &ES;
std::function<void(Error)> ReportError;
std::string RemoteTargetTriple;
uint32_t RemotePointerSize = 0;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index cf419d3..acbc168 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -161,9 +161,9 @@
IntVoidFnTy Fn =
reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
int Result = Fn();
- DEBUG(dbgs() << " Result = " << Result << "\n");
+ LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
}
@@ -180,15 +180,13 @@
for (auto &Arg : Args)
ArgV[Idx++] = Arg.c_str();
ArgV[ArgC] = 0;
- DEBUG(
- for (int Idx = 0; Idx < ArgC; ++Idx) {
- llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n";
- }
- );
+ LLVM_DEBUG(for (int Idx = 0; Idx < ArgC; ++Idx) {
+ llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n";
+ });
- DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
int Result = Fn(ArgC, ArgV.get());
- DEBUG(dbgs() << " Result = " << Result << "\n");
+ LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
}
@@ -199,9 +197,9 @@
VoidVoidFnTy Fn =
reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n");
Fn();
- DEBUG(dbgs() << " Complete.\n");
+ LLVM_DEBUG(dbgs() << " Complete.\n");
return Error::success();
}
@@ -211,7 +209,7 @@
if (I != Allocators.end())
return errorCodeToError(
orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse));
- DEBUG(dbgs() << " Created allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << " Created allocator " << Id << "\n");
Allocators[Id] = Allocator();
return Error::success();
}
@@ -221,15 +219,16 @@
if (I != IndirectStubsOwners.end())
return errorCodeToError(
orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse));
- DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
+ LLVM_DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
IndirectStubsOwners[Id] = ISBlockOwnerList();
return Error::success();
}
Error handleDeregisterEHFrames(JITTargetAddress TAddr, uint32_t Size) {
uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
- DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
- << ", Size = " << Size << " bytes\n");
+ LLVM_DEBUG(dbgs() << " Registering EH frames at "
+ << format("0x%016x", TAddr) << ", Size = " << Size
+ << " bytes\n");
EHFramesDeregister(Addr, Size);
return Error::success();
}
@@ -240,7 +239,7 @@
return errorCodeToError(
orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
Allocators.erase(I);
- DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
+ LLVM_DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
return Error::success();
}
@@ -256,8 +255,8 @@
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
uint32_t NumStubsRequired) {
- DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
- << " stubs.\n");
+ LLVM_DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
+ << " stubs.\n");
auto StubOwnerItr = IndirectStubsOwners.find(Id);
if (StubOwnerItr == IndirectStubsOwners.end())
@@ -328,8 +327,8 @@
Expected<JITTargetAddress> handleGetSymbolAddress(const std::string &Name) {
JITTargetAddress Addr = SymbolLookup(Name);
- DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
- << "\n");
+ LLVM_DEBUG(dbgs() << " Symbol '" << Name
+ << "' = " << format("0x%016x", Addr) << "\n");
return Addr;
}
@@ -340,12 +339,13 @@
uint32_t PageSize = sys::Process::getPageSize();
uint32_t TrampolineSize = TargetT::TrampolineSize;
uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
- DEBUG(dbgs() << " Remote info:\n"
- << " triple = '" << ProcessTriple << "'\n"
- << " pointer size = " << PointerSize << "\n"
- << " page size = " << PageSize << "\n"
- << " trampoline size = " << TrampolineSize << "\n"
- << " indirect stub size = " << IndirectStubSize << "\n");
+ LLVM_DEBUG(dbgs() << " Remote info:\n"
+ << " triple = '" << ProcessTriple << "'\n"
+ << " pointer size = " << PointerSize << "\n"
+ << " page size = " << PageSize << "\n"
+ << " trampoline size = " << TrampolineSize << "\n"
+ << " indirect stub size = " << IndirectStubSize
+ << "\n");
return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
IndirectStubSize);
}
@@ -354,8 +354,8 @@
uint64_t Size) {
uint8_t *Src = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(RSrc));
- DEBUG(dbgs() << " Reading " << Size << " bytes from "
- << format("0x%016x", RSrc) << "\n");
+ LLVM_DEBUG(dbgs() << " Reading " << Size << " bytes from "
+ << format("0x%016x", RSrc) << "\n");
std::vector<uint8_t> Buffer;
Buffer.resize(Size);
@@ -367,8 +367,9 @@
Error handleRegisterEHFrames(JITTargetAddress TAddr, uint32_t Size) {
uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
- DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
- << ", Size = " << Size << " bytes\n");
+ LLVM_DEBUG(dbgs() << " Registering EH frames at "
+ << format("0x%016x", TAddr) << ", Size = " << Size
+ << " bytes\n");
EHFramesRegister(Addr, Size);
return Error::success();
}
@@ -384,8 +385,9 @@
if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align))
return std::move(Err);
- DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
- << " (" << Size << " bytes, alignment " << Align << ")\n");
+ LLVM_DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
+ << " (" << Size << " bytes, alignment " << Align
+ << ")\n");
JITTargetAddress AllocAddr = static_cast<JITTargetAddress>(
reinterpret_cast<uintptr_t>(LocalAllocAddr));
@@ -401,10 +403,11 @@
orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
auto &Allocator = I->second;
void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
- DEBUG(dbgs() << " Allocator " << Id << " set permissions on " << LocalAddr
- << " to " << (Flags & sys::Memory::MF_READ ? 'R' : '-')
- << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
- << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
+ LLVM_DEBUG(dbgs() << " Allocator " << Id << " set permissions on "
+ << LocalAddr << " to "
+ << (Flags & sys::Memory::MF_READ ? 'R' : '-')
+ << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
+ << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
return Allocator.setProtections(LocalAddr, Flags);
}
@@ -414,14 +417,14 @@
}
Error handleWriteMem(DirectBufferWriter DBW) {
- DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
- << format("0x%016x", DBW.getDst()) << "\n");
+ LLVM_DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
+ << format("0x%016x", DBW.getDst()) << "\n");
return Error::success();
}
Error handleWritePtr(JITTargetAddress Addr, JITTargetAddress PtrVal) {
- DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) << " = "
- << format("0x%016x", PtrVal) << "\n");
+ LLVM_DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr)
+ << " = " << format("0x%016x", PtrVal) << "\n");
uintptr_t *Ptr =
reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
*Ptr = static_cast<uintptr_t>(PtrVal);
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
index 569c506..1e5f6ce 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
@@ -14,7 +14,10 @@
#include "llvm/Support/thread.h"
#include <map>
#include <mutex>
+#include <set>
#include <sstream>
+#include <string>
+#include <vector>
namespace llvm {
namespace orc {
@@ -205,6 +208,42 @@
template <typename T>
std::string RPCTypeName<std::vector<T>>::Name;
+template <typename T> class RPCTypeName<std::set<T>> {
+public:
+ static const char *getName() {
+ std::lock_guard<std::mutex> Lock(NameMutex);
+ if (Name.empty())
+ raw_string_ostream(Name)
+ << "std::set<" << RPCTypeName<T>::getName() << ">";
+ return Name.data();
+ }
+
+private:
+ static std::mutex NameMutex;
+ static std::string Name;
+};
+
+template <typename T> std::mutex RPCTypeName<std::set<T>>::NameMutex;
+template <typename T> std::string RPCTypeName<std::set<T>>::Name;
+
+template <typename K, typename V> class RPCTypeName<std::map<K, V>> {
+public:
+ static const char *getName() {
+ std::lock_guard<std::mutex> Lock(NameMutex);
+ if (Name.empty())
+ raw_string_ostream(Name)
+ << "std::map<" << RPCTypeNameSequence<K, V>() << ">";
+ return Name.data();
+ }
+
+private:
+ static std::mutex NameMutex;
+ static std::string Name;
+};
+
+template <typename K, typename V>
+std::mutex RPCTypeName<std::map<K, V>>::NameMutex;
+template <typename K, typename V> std::string RPCTypeName<std::map<K, V>>::Name;
/// The SerializationTraits<ChannelT, T> class describes how to serialize and
/// deserialize an instance of type T to/from an abstract channel of type
@@ -527,15 +566,20 @@
};
/// SerializationTraits default specialization for std::pair.
-template <typename ChannelT, typename T1, typename T2>
-class SerializationTraits<ChannelT, std::pair<T1, T2>> {
+template <typename ChannelT, typename T1, typename T2, typename T3, typename T4>
+class SerializationTraits<ChannelT, std::pair<T1, T2>, std::pair<T3, T4>> {
public:
- static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
- return serializeSeq(C, V.first, V.second);
+ static Error serialize(ChannelT &C, const std::pair<T3, T4> &V) {
+ if (auto Err = SerializationTraits<ChannelT, T1, T3>::serialize(C, V.first))
+ return Err;
+ return SerializationTraits<ChannelT, T2, T4>::serialize(C, V.second);
}
- static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
- return deserializeSeq(C, V.first, V.second);
+ static Error deserialize(ChannelT &C, std::pair<T3, T4> &V) {
+ if (auto Err =
+ SerializationTraits<ChannelT, T1, T3>::deserialize(C, V.first))
+ return Err;
+ return SerializationTraits<ChannelT, T2, T4>::deserialize(C, V.second);
}
};
@@ -589,6 +633,9 @@
/// Deserialize a std::vector<T> to a std::vector<T>.
static Error deserialize(ChannelT &C, std::vector<T> &V) {
+ assert(V.empty() &&
+ "Expected default-constructed vector to deserialize into");
+
uint64_t Count = 0;
if (auto Err = deserializeSeq(C, Count))
return Err;
@@ -602,6 +649,92 @@
}
};
+template <typename ChannelT, typename T, typename T2>
+class SerializationTraits<ChannelT, std::set<T>, std::set<T2>> {
+public:
+ /// Serialize a std::set<T> from std::set<T2>.
+ static Error serialize(ChannelT &C, const std::set<T2> &S) {
+ if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
+ return Err;
+
+ for (const auto &E : S)
+ if (auto Err = SerializationTraits<ChannelT, T, T2>::serialize(C, E))
+ return Err;
+
+ return Error::success();
+ }
+
+ /// Deserialize a std::set<T> to a std::set<T>.
+ static Error deserialize(ChannelT &C, std::set<T2> &S) {
+ assert(S.empty() && "Expected default-constructed set to deserialize into");
+
+ uint64_t Count = 0;
+ if (auto Err = deserializeSeq(C, Count))
+ return Err;
+
+ while (Count-- != 0) {
+ T2 Val;
+ if (auto Err = SerializationTraits<ChannelT, T, T2>::deserialize(C, Val))
+ return Err;
+
+ auto Added = S.insert(Val).second;
+ if (!Added)
+ return make_error<StringError>("Duplicate element in deserialized set",
+ orcError(OrcErrorCode::UnknownORCError));
+ }
+
+ return Error::success();
+ }
+};
+
+template <typename ChannelT, typename K, typename V, typename K2, typename V2>
+class SerializationTraits<ChannelT, std::map<K, V>, std::map<K2, V2>> {
+public:
+ /// Serialize a std::map<K, V> from std::map<K2, V2>.
+ static Error serialize(ChannelT &C, const std::map<K2, V2> &M) {
+ if (auto Err = serializeSeq(C, static_cast<uint64_t>(M.size())))
+ return Err;
+
+ for (const auto &E : M) {
+ if (auto Err =
+ SerializationTraits<ChannelT, K, K2>::serialize(C, E.first))
+ return Err;
+ if (auto Err =
+ SerializationTraits<ChannelT, V, V2>::serialize(C, E.second))
+ return Err;
+ }
+
+ return Error::success();
+ }
+
+ /// Deserialize a std::map<K, V> to a std::map<K, V>.
+ static Error deserialize(ChannelT &C, std::map<K2, V2> &M) {
+ assert(M.empty() && "Expected default-constructed map to deserialize into");
+
+ uint64_t Count = 0;
+ if (auto Err = deserializeSeq(C, Count))
+ return Err;
+
+ while (Count-- != 0) {
+ std::pair<K2, V2> Val;
+ if (auto Err =
+ SerializationTraits<ChannelT, K, K2>::deserialize(C, Val.first))
+ return Err;
+
+ if (auto Err =
+ SerializationTraits<ChannelT, V, V2>::deserialize(C, Val.second))
+ return Err;
+
+ auto Added = M.insert(Val).second;
+ if (!Added)
+ return make_error<StringError>("Duplicate element in deserialized map",
+ orcError(OrcErrorCode::UnknownORCError));
+ }
+
+ return Error::success();
+ }
+};
+
} // end namespace rpc
} // end namespace orc
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index c278cb1..47bd90b 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -1631,7 +1631,7 @@
return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint);
}
-/// \brief Allows a set of asynchrounous calls to be dispatched, and then
+/// Allows a set of asynchrounous calls to be dispatched, and then
/// waited on as a group.
class ParallelCallGroup {
public:
@@ -1640,7 +1640,7 @@
ParallelCallGroup(const ParallelCallGroup &) = delete;
ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
- /// \brief Make as asynchronous call.
+ /// Make as asynchronous call.
template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
const ArgTs &... Args) {
@@ -1669,7 +1669,7 @@
return AsyncDispatch(std::move(WrappedHandler), Args...);
}
- /// \brief Blocks until all calls have been completed and their return value
+ /// Blocks until all calls have been completed and their return value
/// handlers run.
void wait() {
std::unique_lock<std::mutex> Lock(M);
@@ -1683,21 +1683,21 @@
uint32_t NumOutstandingCalls = 0;
};
-/// @brief Convenience class for grouping RPC Functions into APIs that can be
+/// Convenience class for grouping RPC Functions into APIs that can be
/// negotiated as a block.
///
template <typename... Funcs>
class APICalls {
public:
- /// @brief Test whether this API contains Function F.
+ /// Test whether this API contains Function F.
template <typename F>
class Contains {
public:
static const bool value = false;
};
- /// @brief Negotiate all functions in this API.
+ /// Negotiate all functions in this API.
template <typename RPCEndpoint>
static Error negotiate(RPCEndpoint &R) {
return Error::success();
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 8f0d9fa..6510976 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Object/ObjectFile.h"
@@ -35,13 +36,62 @@
namespace llvm {
namespace orc {
+class RTDyldObjectLinkingLayer2 : public ObjectLayer {
+public:
+ /// Functor for receiving object-loaded notifications.
+ using NotifyLoadedFunction =
+ std::function<void(VModuleKey, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
+
+ /// Functor for receiving finalization notifications.
+ using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
+
+ using GetMemoryManagerFunction =
+ std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
+
+ /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// and NotifyFinalized functors.
+ RTDyldObjectLinkingLayer2(
+ ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
+ NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
+ NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
+
+ /// 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) {
+ this->ProcessAllSections = ProcessAllSections;
+ }
+
+private:
+ mutable std::mutex RTDyldLayerMutex;
+ GetMemoryManagerFunction GetMemoryManager;
+ NotifyLoadedFunction NotifyLoaded;
+ NotifyFinalizedFunction NotifyFinalized;
+ bool ProcessAllSections;
+ std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
+ std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
+};
+
class RTDyldObjectLinkingLayerBase {
public:
using ObjectPtr = std::unique_ptr<MemoryBuffer>;
protected:
- /// @brief Holds an object to be allocated/linked as a unit in the JIT.
+ /// Holds an object to be allocated/linked as a unit in the JIT.
///
/// An instance of this class will be created for each object added
/// via JITObjectLayer::addObject. Deleting the instance (via
@@ -81,7 +131,7 @@
};
};
-/// @brief Bare bones object linking layer.
+/// Bare bones object linking layer.
///
/// This class is intended to be used as the base layer for a JIT. It allows
/// object files to be loaded into memory, linked, and the addresses of their
@@ -92,13 +142,18 @@
using RTDyldObjectLinkingLayerBase::ObjectPtr;
- /// @brief Functor for receiving object-loaded notifications.
+ /// Functor for receiving object-loaded notifications.
using NotifyLoadedFtor =
std::function<void(VModuleKey, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &)>;
- /// @brief Functor for receiving finalization notifications.
- using NotifyFinalizedFtor = std::function<void(VModuleKey)>;
+ /// Functor for receiving finalization notifications.
+ using NotifyFinalizedFtor =
+ std::function<void(VModuleKey, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
+
+ /// Functor for receiving deallocation notifications.
+ using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
private:
using OwnedObject = object::OwningBinary<object::ObjectFile>;
@@ -110,21 +165,27 @@
OwnedObject Obj, MemoryManagerPtrT MemMgr,
std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections)
- : MemMgr(std::move(MemMgr)),
+ : K(std::move(K)),
+ Parent(Parent),
+ MemMgr(std::move(MemMgr)),
PFC(llvm::make_unique<PreFinalizeContents>(
- Parent, std::move(K), std::move(Obj), std::move(Resolver),
+ std::move(Obj), std::move(Resolver),
ProcessAllSections)) {
buildInitialSymbolTable(PFC->Obj);
}
~ConcreteLinkedObject() override {
+ if (this->Parent.NotifyFreed)
+ this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
+
MemMgr->deregisterEHFrames();
}
Error finalize() override {
assert(PFC && "mapSectionAddress called on finalized LinkedObject");
- JITSymbolResolverAdapter ResolverAdapter(PFC->Parent.ES, *PFC->Resolver);
+ JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
+ nullptr);
PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
@@ -140,8 +201,8 @@
SymbolTable[KV.first] = KV.second;
}
- if (PFC->Parent.NotifyLoaded)
- PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info);
+ if (Parent.NotifyLoaded)
+ Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
PFC->RTDyld->finalizeWithMemoryManagerLocking();
@@ -149,10 +210,12 @@
return make_error<StringError>(PFC->RTDyld->getErrorString(),
inconvertibleErrorCode());
- if (PFC->Parent.NotifyFinalized)
- PFC->Parent.NotifyFinalized(PFC->K);
+ if (Parent.NotifyFinalized)
+ Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
// Release resources.
+ if (this->Parent.NotifyFreed)
+ ObjForNotify = std::move(PFC->Obj); // needed for callback
PFC = nullptr;
return Error::success();
}
@@ -186,32 +249,37 @@
consumeError(SymbolName.takeError());
continue;
}
+ // FIXME: Raise an error for bad symbols.
auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
+ if (!Flags) {
+ consumeError(Flags.takeError());
+ continue;
+ }
SymbolTable.insert(
- std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
+ std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags)));
}
}
// Contains the information needed prior to finalization: the object files,
// memory manager, resolver, and flags needed for RuntimeDyld.
struct PreFinalizeContents {
- PreFinalizeContents(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
- OwnedObject Obj,
+ PreFinalizeContents(OwnedObject Obj,
std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections)
- : Parent(Parent), K(std::move(K)), Obj(std::move(Obj)),
+ : Obj(std::move(Obj)),
Resolver(std::move(Resolver)),
ProcessAllSections(ProcessAllSections) {}
- RTDyldObjectLinkingLayer &Parent;
- VModuleKey K;
OwnedObject Obj;
std::shared_ptr<SymbolResolver> Resolver;
bool ProcessAllSections;
std::unique_ptr<RuntimeDyld> RTDyld;
};
+ VModuleKey K;
+ RTDyldObjectLinkingLayer &Parent;
MemoryManagerPtrT MemMgr;
+ OwnedObject ObjForNotify;
std::unique_ptr<PreFinalizeContents> PFC;
};
@@ -235,18 +303,21 @@
using ResourcesGetter = std::function<Resources(VModuleKey)>;
- /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
RTDyldObjectLinkingLayer(
ExecutionSession &ES, ResourcesGetter GetResources,
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
- NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
+ NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
+ NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
: ES(ES), GetResources(std::move(GetResources)),
NotifyLoaded(std::move(NotifyLoaded)),
- NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {
+ NotifyFinalized(std::move(NotifyFinalized)),
+ NotifyFreed(std::move(NotifyFreed)),
+ ProcessAllSections(false) {
}
- /// @brief Set the 'ProcessAllSections' flag.
+ /// 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.
@@ -256,7 +327,7 @@
this->ProcessAllSections = ProcessAllSections;
}
- /// @brief Add an object to the JIT.
+ /// Add an object to the JIT.
Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
auto Obj =
@@ -275,7 +346,7 @@
return Error::success();
}
- /// @brief Remove the object associated with VModuleKey K.
+ /// Remove the object associated with VModuleKey K.
///
/// All memory allocated for the object will be freed, and the sections and
/// symbols it provided will no longer be available. No attempt is made to
@@ -290,7 +361,7 @@
return Error::success();
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
@@ -304,7 +375,7 @@
return nullptr;
}
- /// @brief Search for the given named symbol in the context of the loaded
+ /// Search for the given named symbol in the context of the loaded
/// object represented by the VModuleKey K.
/// @param K The VModuleKey for the object to search in.
/// @param Name The name of the symbol to search for.
@@ -317,7 +388,7 @@
return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Map section addresses for the object associated with the
+ /// Map section addresses for the object associated with the
/// VModuleKey K.
void mapSectionAddress(VModuleKey K, const void *LocalAddress,
JITTargetAddress TargetAddr) {
@@ -325,7 +396,7 @@
LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
}
- /// @brief Immediately emit and finalize the object represented by the given
+ /// Immediately emit and finalize the object represented by the given
/// VModuleKey.
/// @param K VModuleKey for object to emit/finalize.
Error emitAndFinalize(VModuleKey K) {
@@ -340,6 +411,7 @@
ResourcesGetter GetResources;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
+ NotifyFreedFtor NotifyFreed;
bool ProcessAllSections = false;
};
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
index b95faaa..955e776 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
@@ -322,7 +322,7 @@
*this, &ThisT::lookupInLogicalDylib);
}
- /// @brief Add an object to the JIT.
+ /// Add an object to the JIT.
///
/// @return A handle that can be used to refer to the loaded object (for
/// symbol searching, finalization, freeing memory, etc.).
@@ -340,26 +340,26 @@
return HandleOrErr.takeError();
}
- /// @brief Remove the given object from the JIT.
+ /// Remove the given object from the JIT.
Error removeObject(ObjHandleT H) {
return this->Remote.template callB<RemoveObject>(H);
}
- /// @brief Search for the given named symbol.
+ /// Search for the given named symbol.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
return remoteToJITSymbol(
this->Remote.template callB<FindSymbol>(Name,
ExportedSymbolsOnly));
}
- /// @brief Search for the given named symbol within the given context.
+ /// Search for the given named symbol within the given context.
JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
return remoteToJITSymbol(
this->Remote.template callB<FindSymbolIn>(H, Name,
ExportedSymbolsOnly));
}
- /// @brief Immediately emit and finalize the object with the given handle.
+ /// Immediately emit and finalize the object with the given handle.
Error emitAndFinalize(ObjHandleT H) {
return this->Remote.template callB<EmitAndFinalize>(H);
}
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
index da40d1c..4c45cfd 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -23,17 +23,20 @@
class SymbolStringPtr;
-/// @brief String pool for symbol names used by the JIT.
+/// String pool for symbol names used by the JIT.
class SymbolStringPool {
friend class SymbolStringPtr;
public:
- /// @brief Create a symbol string pointer from the given string.
+ /// Destroy a SymbolStringPool.
+ ~SymbolStringPool();
+
+ /// Create a symbol string pointer from the given string.
SymbolStringPtr intern(StringRef S);
- /// @brief Remove from the pool any entries that are no longer referenced.
+ /// Remove from the pool any entries that are no longer referenced.
void clearDeadEntries();
- /// @brief Returns true if the pool is empty.
+ /// Returns true if the pool is empty.
bool empty() const;
private:
using RefCountType = std::atomic<size_t>;
@@ -43,7 +46,7 @@
PoolMap Pool;
};
-/// @brief Pointer to a pooled string representing a symbol name.
+/// Pointer to a pooled string representing a symbol name.
class SymbolStringPtr {
friend class SymbolStringPool;
friend bool operator==(const SymbolStringPtr &LHS,
@@ -109,6 +112,13 @@
return LHS.S < RHS.S;
}
+inline SymbolStringPool::~SymbolStringPool() {
+#ifndef NDEBUG
+ clearDeadEntries();
+ assert(Pool.empty() && "Dangling references at pool destruction time");
+#endif // NDEBUG
+}
+
inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
std::lock_guard<std::mutex> Lock(PoolMutex);
PoolMap::iterator I;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index ee75202..23d651f 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -47,6 +47,9 @@
/// newly loaded object.
virtual void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
+
+private:
+ void anchor() override;
};
// RuntimeDyld clients often want to handle the memory management of
@@ -142,6 +145,9 @@
};
typedef std::vector<EHFrame> EHFrameInfos;
EHFrameInfos EHFrames;
+
+private:
+ void anchor() override;
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
index 14da5af..5dd5add 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -65,7 +65,7 @@
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
public:
- /// \brief Information about the loaded object.
+ /// Information about the loaded object.
class LoadedObjectInfo : public llvm::LoadedObjectInfo {
friend class RuntimeDyldImpl;
@@ -88,7 +88,7 @@
ObjSectionToIDMap ObjSecToIDMap;
};
- /// \brief Memory Management.
+ /// Memory Management.
class MemoryManager {
friend class RuntimeDyld;
@@ -170,7 +170,7 @@
bool FinalizationLocked = false;
};
- /// \brief Construct a RuntimeDyld instance.
+ /// Construct a RuntimeDyld instance.
RuntimeDyld(MemoryManager &MemMgr, JITSymbolResolver &Resolver);
RuntimeDyld(const RuntimeDyld &) = delete;
RuntimeDyld &operator=(const RuntimeDyld &) = delete;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index de89f40..13fc5fd 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -27,7 +27,7 @@
class RuntimeDyldCheckerImpl;
class raw_ostream;
-/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has
+/// RuntimeDyld invariant checker for verifying that RuntimeDyld has
/// correctly applied relocations.
///
/// The RuntimeDyldChecker class evaluates expressions against an attached
@@ -74,22 +74,22 @@
MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
~RuntimeDyldChecker();
- // \brief Get the associated RTDyld instance.
+ // Get the associated RTDyld instance.
RuntimeDyld& getRTDyld();
- // \brief Get the associated RTDyld instance.
+ // Get the associated RTDyld instance.
const RuntimeDyld& getRTDyld() const;
- /// \brief Check a single expression against the attached RuntimeDyld
+ /// Check a single expression against the attached RuntimeDyld
/// instance.
bool check(StringRef CheckExpr) const;
- /// \brief Scan the given memory buffer for lines beginning with the string
+ /// Scan the given memory buffer for lines beginning with the string
/// in RulePrefix. The remainder of the line is passed to the check
/// method to be evaluated as an expression.
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
- /// \brief Returns the address of the requested section (or an error message
+ /// Returns the address of the requested section (or an error message
/// in the second element of the pair if the address cannot be found).
///
/// if 'LocalAddress' is true, this returns the address of the section
@@ -99,7 +99,7 @@
StringRef SectionName,
bool LocalAddress);
- /// \brief If there is a section at the given local address, return its load
+ /// If there is a section at the given local address, return its load
/// address, otherwise return none.
Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h b/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h
index d76e371..3cf131c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -111,7 +111,7 @@
void operator=(const SectionMemoryManager &) = delete;
~SectionMemoryManager() override;
- /// \brief Allocates a memory block of (at least) the given size suitable for
+ /// Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
@@ -120,7 +120,7 @@
unsigned SectionID,
StringRef SectionName) override;
- /// \brief Allocates a memory block of (at least) the given size suitable for
+ /// Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
@@ -129,7 +129,7 @@
unsigned SectionID, StringRef SectionName,
bool isReadOnly) override;
- /// \brief Update section-specific memory permissions and other attributes.
+ /// Update section-specific memory permissions and other attributes.
///
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager implementation
@@ -142,7 +142,7 @@
/// \returns true if an error occurred, false otherwise.
bool finalizeMemory(std::string *ErrMsg = nullptr) override;
- /// \brief Invalidate instruction cache for code sections.
+ /// Invalidate instruction cache for code sections.
///
/// Some platforms with separate data cache and instruction cache require
/// explicit cache flush, otherwise JIT code manipulations (like resolved
@@ -182,6 +182,8 @@
std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
unsigned Permissions);
+ void anchor() override;
+
MemoryGroup CodeMem;
MemoryGroup RWDataMem;
MemoryGroup RODataMem;