Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index ca1ce40..67aa09b 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -18,14 +18,12 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
-#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
-#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
+#include "llvm/ExecutionEngine/Orc/Speculation.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constant.h"
@@ -91,9 +89,13 @@
/// Sets the partition function.
void setPartitionFunction(PartitionFunction Partition);
+ /// Sets the ImplSymbolMap
+ void setImplMap(ImplSymbolMap *Imp);
+
/// Emits the given module. This should not be called by clients: it will be
/// called by the JIT when a definition added via the add method is requested.
- void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
+ ThreadSafeModule TSM) override;
private:
struct PerDylibResources {
@@ -117,7 +119,8 @@
void expandPartition(GlobalValueSet &Partition);
- void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM,
+ void emitPartition(std::unique_ptr<MaterializationResponsibility> R,
+ ThreadSafeModule TSM,
IRMaterializationUnit::SymbolNameToDefinitionMap Defs);
mutable std::mutex CODLayerMutex;
@@ -128,609 +131,10 @@
PerDylibResourcesMap DylibResources;
PartitionFunction Partition = compileRequested;
SymbolLinkagePromoter PromoteSymbols;
-};
-
-/// 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
-/// added to the layer below. When a stub is called it triggers the extraction
-/// of the function body from the original module. The extracted body is then
-/// compiled and executed.
-template <typename BaseLayerT,
- typename CompileCallbackMgrT = JITCompileCallbackManager,
- typename IndirectStubsMgrT = IndirectStubsManager>
-class LegacyCompileOnDemandLayer {
-private:
- template <typename MaterializerFtor>
- class LambdaMaterializer final : public ValueMaterializer {
- public:
- LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
-
- Value *materialize(Value *V) final { return M(V); }
-
- private:
- MaterializerFtor M;
- };
-
- template <typename MaterializerFtor>
- LambdaMaterializer<MaterializerFtor>
- createLambdaMaterializer(MaterializerFtor M) {
- return LambdaMaterializer<MaterializerFtor>(std::move(M));
- }
-
- // Provide type-erasure for the Modules and MemoryManagers.
- template <typename ResourceT>
- class ResourceOwner {
- public:
- ResourceOwner() = default;
- ResourceOwner(const ResourceOwner &) = delete;
- ResourceOwner &operator=(const ResourceOwner &) = delete;
- virtual ~ResourceOwner() = default;
-
- virtual ResourceT& getResource() const = 0;
- };
-
- template <typename ResourceT, typename ResourcePtrT>
- class ResourceOwnerImpl : public ResourceOwner<ResourceT> {
- public:
- ResourceOwnerImpl(ResourcePtrT ResourcePtr)
- : ResourcePtr(std::move(ResourcePtr)) {}
-
- ResourceT& getResource() const override { return *ResourcePtr; }
-
- private:
- ResourcePtrT ResourcePtr;
- };
-
- template <typename ResourceT, typename ResourcePtrT>
- std::unique_ptr<ResourceOwner<ResourceT>>
- wrapOwnership(ResourcePtrT ResourcePtr) {
- using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>;
- return llvm::make_unique<RO>(std::move(ResourcePtr));
- }
-
- struct LogicalDylib {
- struct SourceModuleEntry {
- std::unique_ptr<Module> SourceMod;
- std::set<Function*> StubsToClone;
- };
-
- using SourceModulesList = std::vector<SourceModuleEntry>;
- using SourceModuleHandle = typename SourceModulesList::size_type;
-
- LogicalDylib() = default;
-
- LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver,
- std::unique_ptr<IndirectStubsMgrT> StubsMgr)
- : K(std::move(K)), BackingResolver(std::move(BackingResolver)),
- StubsMgr(std::move(StubsMgr)) {}
-
- SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) {
- SourceModuleHandle H = SourceModules.size();
- SourceModules.push_back(SourceModuleEntry());
- SourceModules.back().SourceMod = std::move(M);
- return H;
- }
-
- Module& getSourceModule(SourceModuleHandle H) {
- return *SourceModules[H].SourceMod;
- }
-
- std::set<Function*>& getStubsToClone(SourceModuleHandle H) {
- return SourceModules[H].StubsToClone;
- }
-
- JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name,
- bool ExportedSymbolsOnly) {
- if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly))
- return Sym;
- for (auto BLK : BaseLayerVModuleKeys)
- if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- return nullptr;
- }
-
- Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
- for (auto &BLK : BaseLayerVModuleKeys)
- if (auto Err = BaseLayer.removeModule(BLK))
- return Err;
- return Error::success();
- }
-
- VModuleKey K;
- std::shared_ptr<SymbolResolver> BackingResolver;
- std::unique_ptr<IndirectStubsMgrT> StubsMgr;
- SymbolLinkagePromoter PromoteSymbols;
- SourceModulesList SourceModules;
- std::vector<VModuleKey> BaseLayerVModuleKeys;
- };
-
-public:
-
- /// Module partitioning functor.
- using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
-
- /// Builder for IndirectStubsManagers.
- using IndirectStubsManagerBuilderT =
- std::function<std::unique_ptr<IndirectStubsMgrT>()>;
-
- using SymbolResolverGetter =
- std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>;
-
- using SymbolResolverSetter =
- std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
-
- /// Construct a compile-on-demand layer instance.
- LegacyCompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer,
- SymbolResolverGetter GetSymbolResolver,
- SymbolResolverSetter SetSymbolResolver,
- PartitioningFtor Partition,
- CompileCallbackMgrT &CallbackMgr,
- IndirectStubsManagerBuilderT CreateIndirectStubsManager,
- bool CloneStubsIntoPartitions = true)
- : ES(ES), BaseLayer(BaseLayer),
- GetSymbolResolver(std::move(GetSymbolResolver)),
- SetSymbolResolver(std::move(SetSymbolResolver)),
- Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
- CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
- CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
-
- ~LegacyCompileOnDemandLayer() {
- // FIXME: Report error on log.
- while (!LogicalDylibs.empty())
- consumeError(removeModule(LogicalDylibs.begin()->first));
- }
-
- /// 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");
- auto I = LogicalDylibs.insert(
- LogicalDylibs.end(),
- std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K),
- CreateIndirectStubsManager())));
-
- return addLogicalModule(I->second, std::move(M));
- }
-
- /// Add extra modules to an existing logical module.
- Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
- return addLogicalModule(LogicalDylibs[K], std::move(M));
- }
-
- /// 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.
- Error removeModule(VModuleKey K) {
- auto I = LogicalDylibs.find(K);
- assert(I != LogicalDylibs.end() && "VModuleKey K not valid here");
- auto Err = I->second.removeModulesFromBaseLayer(BaseLayer);
- LogicalDylibs.erase(I);
- return Err;
- }
-
- /// 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.
- JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
- for (auto &KV : LogicalDylibs) {
- if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly))
- return Sym;
- if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- }
- return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
- }
-
- /// 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) {
- assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here");
- return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
- }
-
- /// 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.
- //
- // FIXME: We should track and free associated resources (unused compile
- // callbacks, uncompiled IR, and no-longer-needed/reachable function
- // implementations).
- Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) {
- //Find out which logical dylib contains our symbol
- auto LDI = LogicalDylibs.begin();
- for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) {
- if (auto LMResources =
- LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) {
- Module &SrcM = LMResources->SourceModule->getResource();
- std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout());
- if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName,
- FnBodyAddr))
- return Err;
- return Error::success();
- }
- }
- return make_error<JITSymbolNotFound>(FuncName);
- }
-
-private:
- Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
-
- // Rename anonymous globals and promote linkage to ensure that everything
- // will resolve properly after we partition SrcM.
- LD.PromoteSymbols(*SrcMPtr);
-
- // Create a logical module handle for SrcM within the logical dylib.
- Module &SrcM = *SrcMPtr;
- auto LMId = LD.addSourceModule(std::move(SrcMPtr));
-
- // Create stub functions.
- const DataLayout &DL = SrcM.getDataLayout();
- {
- typename IndirectStubsMgrT::StubInitsMap StubInits;
- for (auto &F : SrcM) {
- // Skip declarations.
- if (F.isDeclaration())
- continue;
-
- // Skip weak functions for which we already have definitions.
- auto MangledName = mangle(F.getName(), DL);
- if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
- if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
- continue;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- }
-
- // Record all functions defined by this module.
- if (CloneStubsIntoPartitions)
- LD.getStubsToClone(LMId).insert(&F);
-
- // Create a callback, associate it with the stub for the function,
- // and set the compile action to compile the partition containing the
- // function.
- 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(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
- else
- return CCAddr.takeError();
- }
-
- if (auto Err = LD.StubsMgr->createStubs(StubInits))
- return Err;
- }
-
- // If this module doesn't contain any globals, aliases, or module flags then
- // we can bail out early and avoid the overhead of creating and managing an
- // empty globals module.
- if (SrcM.global_empty() && SrcM.alias_empty() &&
- !SrcM.getModuleFlagsMetadata())
- return Error::success();
-
- // Create the GlobalValues module.
- auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
- SrcM.getContext());
- GVsM->setDataLayout(DL);
-
- ValueToValueMapTy VMap;
-
- // Clone global variable decls.
- for (auto &GV : SrcM.globals())
- if (!GV.isDeclaration() && !VMap.count(&GV))
- cloneGlobalVariableDecl(*GVsM, GV, &VMap);
-
- // And the aliases.
- for (auto &A : SrcM.aliases())
- if (!VMap.count(&A))
- cloneGlobalAliasDecl(*GVsM, A, VMap);
-
- // Clone the module flags.
- cloneModuleFlagsMetadata(*GVsM, SrcM, VMap);
-
- // Now we need to clone the GV and alias initializers.
-
- // Initializers may refer to functions declared (but not defined) in this
- // module. Build a materializer to clone decls on demand.
- auto Materializer = createLambdaMaterializer(
- [&LD, &GVsM](Value *V) -> Value* {
- if (auto *F = dyn_cast<Function>(V)) {
- // Decls in the original module just get cloned.
- if (F->isDeclaration())
- return cloneFunctionDecl(*GVsM, *F);
-
- // Definitions in the original module (which we have emitted stubs
- // for at this point) get turned into a constant alias to the stub
- // instead.
- const DataLayout &DL = GVsM->getDataLayout();
- std::string FName = mangle(F->getName(), DL);
- unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
- JITTargetAddress StubAddr =
- LD.StubsMgr->findStub(FName, false).getAddress();
-
- ConstantInt *StubAddrCI =
- ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
- Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
- StubAddrCI, F->getType());
- return GlobalAlias::create(F->getFunctionType(),
- F->getType()->getAddressSpace(),
- F->getLinkage(), F->getName(),
- Init, GVsM.get());
- }
- // else....
- return nullptr;
- });
-
- // Clone the global variable initializers.
- for (auto &GV : SrcM.globals())
- if (!GV.isDeclaration())
- moveGlobalVariableInitializer(GV, VMap, &Materializer);
-
- // Clone the global alias initializers.
- for (auto &A : SrcM.aliases()) {
- auto *NewA = cast<GlobalAlias>(VMap[&A]);
- assert(NewA && "Alias not cloned?");
- Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
- &Materializer);
- NewA->setAliasee(cast<Constant>(Init));
- }
-
- // 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;
-
- if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
-
- return nullptr;
- };
-
- auto GVsResolver = createSymbolResolver(
- [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
- auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
-
- if (!RS) {
- logAllUnhandledErrors(
- RS.takeError(), errs(),
- "CODLayer/GVsResolver responsibility set lookup failed: ");
- return SymbolNameSet();
- }
-
- if (RS->size() == Symbols.size())
- return *RS;
-
- SymbolNameSet NotFoundViaLegacyLookup;
- for (auto &S : Symbols)
- if (!RS->count(S))
- NotFoundViaLegacyLookup.insert(S);
- auto RS2 =
- LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
-
- for (auto &S : RS2)
- (*RS).insert(S);
-
- return *RS;
- },
- [this, &LD,
- LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) {
- auto NotFoundViaLegacyLookup =
- lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
- return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
- });
-
- SetSymbolResolver(LD.K, std::move(GVsResolver));
-
- if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM)))
- return Err;
-
- LD.BaseLayerVModuleKeys.push_back(LD.K);
-
- return Error::success();
- }
-
- static std::string mangle(StringRef Name, const DataLayout &DL) {
- std::string MangledName;
- {
- raw_string_ostream MangledNameStream(MangledName);
- Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
- }
- return MangledName;
- }
-
- Expected<JITTargetAddress>
- extractAndCompile(LogicalDylib &LD,
- typename LogicalDylib::SourceModuleHandle LMId,
- Function &F) {
- Module &SrcM = LD.getSourceModule(LMId);
-
- // If F is a declaration we must already have compiled it.
- if (F.isDeclaration())
- return 0;
-
- // Grab the name of the function being called here.
- std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
-
- JITTargetAddress CalledAddr = 0;
- auto Part = Partition(F);
- if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) {
- auto &PartKey = *PartKeyOrErr;
- for (auto *SubF : Part) {
- std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
- if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) {
- if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
- JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
-
- // If this is the function we're calling record the address so we can
- // return it from this function.
- if (SubF == &F)
- CalledAddr = FnBodyAddr;
-
- // Update the function body pointer for the stub.
- if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
- return 0;
-
- } else
- return FnBodyAddrOrErr.takeError();
- } else if (auto Err = FnBodySym.takeError())
- return std::move(Err);
- else
- llvm_unreachable("Function not emitted for partition");
- }
-
- LD.BaseLayerVModuleKeys.push_back(PartKey);
- } else
- return PartKeyOrErr.takeError();
-
- return CalledAddr;
- }
-
- template <typename PartitionT>
- Expected<VModuleKey>
- emitPartition(LogicalDylib &LD,
- typename LogicalDylib::SourceModuleHandle LMId,
- const PartitionT &Part) {
- Module &SrcM = LD.getSourceModule(LMId);
-
- // Create the module.
- std::string NewName = SrcM.getName();
- for (auto *F : Part) {
- NewName += ".";
- NewName += F->getName();
- }
-
- auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
- M->setDataLayout(SrcM.getDataLayout());
- ValueToValueMapTy VMap;
-
- auto Materializer = createLambdaMaterializer([&LD, &LMId,
- &M](Value *V) -> Value * {
- if (auto *GV = dyn_cast<GlobalVariable>(V))
- return cloneGlobalVariableDecl(*M, *GV);
-
- if (auto *F = dyn_cast<Function>(V)) {
- // Check whether we want to clone an available_externally definition.
- if (!LD.getStubsToClone(LMId).count(F))
- return cloneFunctionDecl(*M, *F);
-
- // Ok - we want an inlinable stub. For that to work we need a decl
- // for the stub pointer.
- auto *StubPtr = createImplPointer(*F->getType(), *M,
- F->getName() + "$stub_ptr", nullptr);
- auto *ClonedF = cloneFunctionDecl(*M, *F);
- makeStub(*ClonedF, *StubPtr);
- ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
- ClonedF->addFnAttr(Attribute::AlwaysInline);
- return ClonedF;
- }
-
- if (auto *A = dyn_cast<GlobalAlias>(V)) {
- auto *Ty = A->getValueType();
- if (Ty->isFunctionTy())
- return Function::Create(cast<FunctionType>(Ty),
- GlobalValue::ExternalLinkage, A->getName(),
- M.get());
-
- return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
- nullptr, A->getName(), nullptr,
- GlobalValue::NotThreadLocal,
- A->getType()->getAddressSpace());
- }
-
- return nullptr;
- });
-
- // Create decls in the new module.
- for (auto *F : Part)
- cloneFunctionDecl(*M, *F, &VMap);
-
- // Move the function bodies.
- for (auto *F : Part)
- moveFunctionBody(*F, VMap, &Materializer);
-
- auto K = ES.allocateVModule();
-
- auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
- return LD.findSymbol(BaseLayer, Name, false);
- };
-
- // Create memory manager and symbol resolver.
- auto Resolver = createSymbolResolver(
- [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
- auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
- if (!RS) {
- logAllUnhandledErrors(
- RS.takeError(), errs(),
- "CODLayer/SubResolver responsibility set lookup failed: ");
- return SymbolNameSet();
- }
-
- if (RS->size() == Symbols.size())
- return *RS;
-
- SymbolNameSet NotFoundViaLegacyLookup;
- for (auto &S : Symbols)
- if (!RS->count(S))
- NotFoundViaLegacyLookup.insert(S);
-
- auto RS2 =
- LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
-
- for (auto &S : RS2)
- (*RS).insert(S);
-
- return *RS;
- },
- [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
- SymbolNameSet Symbols) {
- auto NotFoundViaLegacyLookup =
- lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
- return LD.BackingResolver->lookup(Q,
- std::move(NotFoundViaLegacyLookup));
- });
- SetSymbolResolver(K, std::move(Resolver));
-
- if (auto Err = BaseLayer.addModule(std::move(K), std::move(M)))
- return std::move(Err);
-
- return K;
- }
-
- ExecutionSession &ES;
- BaseLayerT &BaseLayer;
- SymbolResolverGetter GetSymbolResolver;
- SymbolResolverSetter SetSymbolResolver;
- PartitioningFtor Partition;
- CompileCallbackMgrT &CompileCallbackMgr;
- IndirectStubsManagerBuilderT CreateIndirectStubsManager;
-
- std::map<VModuleKey, LogicalDylib> LogicalDylibs;
- bool CloneStubsIntoPartitions;
+ ImplSymbolMap *AliaseeImpls = nullptr;
};
} // end namespace orc
-
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index 1585925..c7ba572 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -13,12 +13,13 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <memory>
namespace llvm {
-class JITTargetMachineBuilder;
class MCContext;
class MemoryBuffer;
class Module;
@@ -27,24 +28,31 @@
namespace orc {
+IRSymbolMapper::ManglingOptions
+irManglingOptionsFromTargetOptions(const TargetOptions &Opts);
+
/// 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 ConcurrentIRCompiler below.
-class SimpleCompiler {
+class SimpleCompiler : public IRCompileLayer::IRCompiler {
public:
using CompileResult = std::unique_ptr<MemoryBuffer>;
/// Construct a simple compile functor with the given target.
SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
- : TM(TM), ObjCache(ObjCache) {}
+ : IRCompiler(irManglingOptionsFromTargetOptions(TM.Options)), TM(TM),
+ ObjCache(ObjCache) {}
/// Set an ObjectCache to query before compiling.
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
/// Compile a Module to an ObjectFile.
- CompileResult operator()(Module &M);
+ Expected<CompileResult> operator()(Module &M) override;
private:
+ IRSymbolMapper::ManglingOptions
+ manglingOptionsForTargetMachine(const TargetMachine &TM);
+
CompileResult tryToLoadFromObjectCache(const Module &M);
void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer);
@@ -52,18 +60,34 @@
ObjectCache *ObjCache = nullptr;
};
+/// A SimpleCompiler that owns its TargetMachine.
+///
+/// This convenient for clients who don't want to own their TargetMachines,
+/// e.g. LLJIT.
+class TMOwningSimpleCompiler : public SimpleCompiler {
+public:
+ TMOwningSimpleCompiler(std::unique_ptr<TargetMachine> TM,
+ ObjectCache *ObjCache = nullptr)
+ : SimpleCompiler(*TM, ObjCache), TM(std::move(TM)) {}
+
+private:
+ // FIXME: shared because std::functions (and consequently
+ // IRCompileLayer::CompileFunction) are not moveable.
+ std::shared_ptr<llvm::TargetMachine> TM;
+};
+
/// A thread-safe version of SimpleCompiler.
///
/// This class creates a new TargetMachine and SimpleCompiler instance for each
/// compile.
-class ConcurrentIRCompiler {
+class ConcurrentIRCompiler : public IRCompileLayer::IRCompiler {
public:
ConcurrentIRCompiler(JITTargetMachineBuilder JTMB,
ObjectCache *ObjCache = nullptr);
void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; }
- std::unique_ptr<MemoryBuffer> operator()(Module &M);
+ Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) override;
private:
JITTargetMachineBuilder JTMB;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
index 016fd82..4a4b58e 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
@@ -14,16 +14,19 @@
#define LLVM_EXECUTIONENGINE_ORC_CORE_H
#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
-#include "llvm/IR/Module.h"
+#include "llvm/ExecutionEngine/OrcV1Deprecation.h"
#include "llvm/Support/Debug.h"
+#include <atomic>
#include <memory>
#include <vector>
-#define DEBUG_TYPE "orc"
-
namespace llvm {
namespace orc {
@@ -33,29 +36,333 @@
class MaterializationUnit;
class MaterializationResponsibility;
class JITDylib;
+class ResourceTracker;
+class InProgressLookupState;
+
enum class SymbolState : uint8_t;
-/// VModuleKey provides a unique identifier (allocated and managed by
-/// ExecutionSessions) for a module added to the JIT.
-using VModuleKey = uint64_t;
+using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
+using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
+
+using ResourceKey = uintptr_t;
+
+/// API to remove / transfer ownership of JIT resources.
+class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
+private:
+ friend class ExecutionSession;
+ friend class JITDylib;
+ friend class MaterializationResponsibility;
+
+public:
+ ResourceTracker(const ResourceTracker &) = delete;
+ ResourceTracker &operator=(const ResourceTracker &) = delete;
+ ResourceTracker(ResourceTracker &&) = delete;
+ ResourceTracker &operator=(ResourceTracker &&) = delete;
+
+ ~ResourceTracker();
+
+ /// Return the JITDylib targeted by this tracker.
+ JITDylib &getJITDylib() const {
+ return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
+ ~static_cast<uintptr_t>(1));
+ }
+
+ /// Remove all resources associated with this key.
+ Error remove();
+
+ /// Transfer all resources associated with this key to the given
+ /// tracker, which must target the same JITDylib as this one.
+ void transferTo(ResourceTracker &DstRT);
+
+ /// Return true if this tracker has become defunct.
+ bool isDefunct() const { return JDAndFlag.load() & 0x1; }
+
+ /// Returns the key associated with this tracker.
+ /// This method should not be used except for debug logging: there is no
+ /// guarantee that the returned value will remain valid.
+ ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
+
+private:
+ ResourceTracker(JITDylibSP JD);
+
+ void makeDefunct();
+
+ std::atomic_uintptr_t JDAndFlag;
+};
+
+/// Listens for ResourceTracker operations.
+class ResourceManager {
+public:
+ virtual ~ResourceManager();
+ virtual Error handleRemoveResources(ResourceKey K) = 0;
+ virtual void handleTransferResources(ResourceKey DstK, ResourceKey SrcK) = 0;
+};
/// A set of symbol names (represented by SymbolStringPtrs for
// efficiency).
using SymbolNameSet = DenseSet<SymbolStringPtr>;
+/// A vector of symbol names.
+using SymbolNameVector = std::vector<SymbolStringPtr>;
+
/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
-/// (address/flags pairs).
+/// (address/flags pairs).
using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
-/// A base class for materialization failures that allows the failing
-/// symbols to be obtained for logging.
+/// A map from JITDylibs to sets of symbols.
using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
-/// A list of (JITDylib*, bool) pairs.
-using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
+/// Lookup flags that apply to each dylib in the search order for a lookup.
+///
+/// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
+/// only symbols in that Dylib's interface will be searched. If
+/// MatchHiddenSymbols is used then symbols with hidden visibility will match
+/// as well.
+enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
+
+/// Lookup flags that apply to each symbol in a lookup.
+///
+/// If RequiredSymbol is used (the default) for a given symbol then that symbol
+/// must be found during the lookup or the lookup will fail returning a
+/// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
+/// symbol is not found then the query will continue, and no result for the
+/// missing symbol will be present in the result (assuming the rest of the
+/// lookup succeeds).
+enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
+
+/// Describes the kind of lookup being performed. The lookup kind is passed to
+/// symbol generators (if they're invoked) to help them determine what
+/// definitions to generate.
+///
+/// Static -- Lookup is being performed as-if at static link time (e.g.
+/// generators representing static archives should pull in new
+/// definitions).
+///
+/// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
+/// representing static archives should not pull in new definitions).
+enum class LookupKind { Static, DLSym };
+
+/// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
+/// order during symbol lookup.
+using JITDylibSearchOrder =
+ std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
+
+/// Convenience function for creating a search order from an ArrayRef of
+/// JITDylib*, all with the same flags.
+inline JITDylibSearchOrder makeJITDylibSearchOrder(
+ ArrayRef<JITDylib *> JDs,
+ JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
+ JITDylibSearchOrder O;
+ O.reserve(JDs.size());
+ for (auto *JD : JDs)
+ O.push_back(std::make_pair(JD, Flags));
+ return O;
+}
+
+/// A set of symbols to look up, each associated with a SymbolLookupFlags
+/// value.
+///
+/// This class is backed by a vector and optimized for fast insertion,
+/// deletion and iteration. It does not guarantee a stable order between
+/// operations, and will not automatically detect duplicate elements (they
+/// can be manually checked by calling the validate method).
+class SymbolLookupSet {
+public:
+ using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
+ using UnderlyingVector = std::vector<value_type>;
+ using iterator = UnderlyingVector::iterator;
+ using const_iterator = UnderlyingVector::const_iterator;
+
+ SymbolLookupSet() = default;
+
+ explicit SymbolLookupSet(
+ SymbolStringPtr Name,
+ SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
+ add(std::move(Name), Flags);
+ }
+
+ /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
+ explicit SymbolLookupSet(
+ std::initializer_list<SymbolStringPtr> Names,
+ SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
+ Symbols.reserve(Names.size());
+ for (auto &Name : Names)
+ add(std::move(Name), Flags);
+ }
+
+ /// Construct a SymbolLookupSet from a SymbolNameSet with the given
+ /// Flags used for each value.
+ explicit SymbolLookupSet(
+ const SymbolNameSet &Names,
+ SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
+ Symbols.reserve(Names.size());
+ for (const auto &Name : Names)
+ add(Name, Flags);
+ }
+
+ /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
+ /// used for each value.
+ /// If the ArrayRef contains duplicates it is up to the client to remove these
+ /// before using this instance for lookup.
+ explicit SymbolLookupSet(
+ ArrayRef<SymbolStringPtr> Names,
+ SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
+ Symbols.reserve(Names.size());
+ for (const auto &Name : Names)
+ add(Name, Flags);
+ }
+
+ /// Add an element to the set. The client is responsible for checking that
+ /// duplicates are not added.
+ SymbolLookupSet &
+ add(SymbolStringPtr Name,
+ SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
+ Symbols.push_back(std::make_pair(std::move(Name), Flags));
+ return *this;
+ }
+
+ /// Quickly append one lookup set to another.
+ SymbolLookupSet &append(SymbolLookupSet Other) {
+ Symbols.reserve(Symbols.size() + Other.size());
+ for (auto &KV : Other)
+ Symbols.push_back(std::move(KV));
+ return *this;
+ }
+
+ bool empty() const { return Symbols.empty(); }
+ UnderlyingVector::size_type size() const { return Symbols.size(); }
+ iterator begin() { return Symbols.begin(); }
+ iterator end() { return Symbols.end(); }
+ const_iterator begin() const { return Symbols.begin(); }
+ const_iterator end() const { return Symbols.end(); }
+
+ /// Removes the Ith element of the vector, replacing it with the last element.
+ void remove(UnderlyingVector::size_type I) {
+ std::swap(Symbols[I], Symbols.back());
+ Symbols.pop_back();
+ }
+
+ /// Removes the element pointed to by the given iterator. This iterator and
+ /// all subsequent ones (including end()) are invalidated.
+ void remove(iterator I) { remove(I - begin()); }
+
+ /// Removes all elements matching the given predicate, which must be callable
+ /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
+ template <typename PredFn> void remove_if(PredFn &&Pred) {
+ UnderlyingVector::size_type I = 0;
+ while (I != Symbols.size()) {
+ const auto &Name = Symbols[I].first;
+ auto Flags = Symbols[I].second;
+ if (Pred(Name, Flags))
+ remove(I);
+ else
+ ++I;
+ }
+ }
+
+ /// Loop over the elements of this SymbolLookupSet, applying the Body function
+ /// to each one. Body must be callable as
+ /// bool(const SymbolStringPtr &, SymbolLookupFlags).
+ /// If Body returns true then the element just passed in is removed from the
+ /// set. If Body returns false then the element is retained.
+ template <typename BodyFn>
+ auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
+ std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
+ std::declval<SymbolLookupFlags>())),
+ bool>::value> {
+ UnderlyingVector::size_type I = 0;
+ while (I != Symbols.size()) {
+ const auto &Name = Symbols[I].first;
+ auto Flags = Symbols[I].second;
+ if (Body(Name, Flags))
+ remove(I);
+ else
+ ++I;
+ }
+ }
+
+ /// Loop over the elements of this SymbolLookupSet, applying the Body function
+ /// to each one. Body must be callable as
+ /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
+ /// If Body returns a failure value, the loop exits immediately. If Body
+ /// returns true then the element just passed in is removed from the set. If
+ /// Body returns false then the element is retained.
+ template <typename BodyFn>
+ auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
+ std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
+ std::declval<SymbolLookupFlags>())),
+ Expected<bool>>::value,
+ Error> {
+ UnderlyingVector::size_type I = 0;
+ while (I != Symbols.size()) {
+ const auto &Name = Symbols[I].first;
+ auto Flags = Symbols[I].second;
+ auto Remove = Body(Name, Flags);
+ if (!Remove)
+ return Remove.takeError();
+ if (*Remove)
+ remove(I);
+ else
+ ++I;
+ }
+ return Error::success();
+ }
+
+ /// Construct a SymbolNameVector from this instance by dropping the Flags
+ /// values.
+ SymbolNameVector getSymbolNames() const {
+ SymbolNameVector Names;
+ Names.reserve(Symbols.size());
+ for (auto &KV : Symbols)
+ Names.push_back(KV.first);
+ return Names;
+ }
+
+ /// Sort the lookup set by pointer value. This sort is fast but sensitive to
+ /// allocation order and so should not be used where a consistent order is
+ /// required.
+ void sortByAddress() {
+ llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
+ return LHS.first < RHS.first;
+ });
+ }
+
+ /// Sort the lookup set lexicographically. This sort is slow but the order
+ /// is unaffected by allocation order.
+ void sortByName() {
+ llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
+ return *LHS.first < *RHS.first;
+ });
+ }
+
+ /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
+ /// by construction, this method can be used to turn it into a proper set.
+ void removeDuplicates() {
+ sortByAddress();
+ auto LastI = std::unique(Symbols.begin(), Symbols.end());
+ Symbols.erase(LastI, Symbols.end());
+ }
+
+#ifndef NDEBUG
+ /// Returns true if this set contains any duplicates. This should only be used
+ /// in assertions.
+ bool containsDuplicates() {
+ if (Symbols.size() < 2)
+ return false;
+ sortByAddress();
+ for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
+ if (Symbols[I].first == Symbols[I - 1].first)
+ return true;
+ return false;
+ }
+#endif
+
+private:
+ UnderlyingVector Symbols;
+};
struct SymbolAliasMapEntry {
SymbolAliasMapEntry() = default;
@@ -69,45 +376,8 @@
/// A map of Symbols to (Symbol, Flags) pairs.
using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
-/// Render a SymbolStringPtr.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
-
-/// Render a SymbolNameSet.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
-
-/// Render a SymbolFlagsMap entry.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV);
-
-/// Render a SymbolMap entry.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV);
-
-/// Render a SymbolFlagsMap.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
-
-/// Render a SymbolMap.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
-
-/// Render a SymbolDependenceMap entry.
-raw_ostream &operator<<(raw_ostream &OS,
- const SymbolDependenceMap::value_type &KV);
-
-/// Render a SymbolDependendeMap.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
-
-/// Render a MaterializationUnit.
-raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
-
-/// Render a JITDylibSearchList.
-raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
-
-/// Render a SymbolAliasMap.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases);
-
-/// Render a SymbolState.
-raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S);
-
/// Callback to notify client that symbols have been resolved.
-using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
+using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
/// Callback to register the dependencies for a given query.
using RegisterDependenciesFunction =
@@ -117,19 +387,31 @@
/// are no dependants to register with.
extern RegisterDependenciesFunction NoDependenciesToRegister;
+class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
+public:
+ static char ID;
+
+ ResourceTrackerDefunct(ResourceTrackerSP RT);
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+
+private:
+ ResourceTrackerSP RT;
+};
+
/// Used to notify a JITDylib that the given set of symbols failed to
/// materialize.
class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
public:
static char ID;
- FailedToMaterialize(SymbolNameSet Symbols);
+ FailedToMaterialize(std::shared_ptr<SymbolDependenceMap> Symbols);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
- const SymbolNameSet &getSymbols() const { return Symbols; }
+ const SymbolDependenceMap &getSymbols() const { return *Symbols; }
private:
- SymbolNameSet Symbols;
+ std::shared_ptr<SymbolDependenceMap> Symbols;
};
/// Used to notify clients when symbols can not be found during a lookup.
@@ -138,12 +420,13 @@
static char ID;
SymbolsNotFound(SymbolNameSet Symbols);
+ SymbolsNotFound(SymbolNameVector Symbols);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
- const SymbolNameSet &getSymbols() const { return Symbols; }
+ const SymbolNameVector &getSymbols() const { return Symbols; }
private:
- SymbolNameSet Symbols;
+ SymbolNameVector Symbols;
};
/// Used to notify clients that a set of symbols could not be removed.
@@ -160,6 +443,44 @@
SymbolNameSet Symbols;
};
+/// Errors of this type should be returned if a module fails to include
+/// definitions that are claimed by the module's associated
+/// MaterializationResponsibility. If this error is returned it is indicative of
+/// a broken transformation / compiler / object cache.
+class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
+public:
+ static char ID;
+
+ MissingSymbolDefinitions(std::string ModuleName, SymbolNameVector Symbols)
+ : ModuleName(std::move(ModuleName)), Symbols(std::move(Symbols)) {}
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const std::string &getModuleName() const { return ModuleName; }
+ const SymbolNameVector &getSymbols() const { return Symbols; }
+private:
+ std::string ModuleName;
+ SymbolNameVector Symbols;
+};
+
+/// Errors of this type should be returned if a module contains definitions for
+/// symbols that are not claimed by the module's associated
+/// MaterializationResponsibility. If this error is returned it is indicative of
+/// a broken transformation / compiler / object cache.
+class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
+public:
+ static char ID;
+
+ UnexpectedSymbolDefinitions(std::string ModuleName, SymbolNameVector Symbols)
+ : ModuleName(std::move(ModuleName)), Symbols(std::move(Symbols)) {}
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const std::string &getModuleName() const { return ModuleName; }
+ const SymbolNameVector &getSymbols() const { return Symbols; }
+private:
+ std::string ModuleName;
+ SymbolNameVector Symbols;
+};
+
/// Tracks responsibility for materialization, and mediates interactions between
/// MaterializationUnits and JDs.
///
@@ -168,9 +489,10 @@
/// emit symbols, or abandon materialization by notifying any unmaterialized
/// symbols of an error.
class MaterializationResponsibility {
- friend class MaterializationUnit;
+ friend class ExecutionSession;
+
public:
- MaterializationResponsibility(MaterializationResponsibility &&) = default;
+ MaterializationResponsibility(MaterializationResponsibility &&) = delete;
MaterializationResponsibility &
operator=(MaterializationResponsibility &&) = delete;
@@ -179,12 +501,15 @@
/// emitted or notified of an error.
~MaterializationResponsibility();
+ /// Returns the ResourceTracker for this instance.
+ template <typename Func> Error withResourceKeyDo(Func &&F) const;
+
/// Returns the target JITDylib that these symbols are being materialized
/// into.
- JITDylib &getTargetJITDylib() const { return JD; }
+ JITDylib &getTargetJITDylib() const { return *JD; }
- /// Returns the VModuleKey for this instance.
- VModuleKey getVModuleKey() const { return K; }
+ /// Returns the ExecutionSession for this instance.
+ ExecutionSession &getExecutionSession();
/// Returns the symbol flags map for this responsibility instance.
/// Note: The returned flags may have transient flags (Lazy, Materializing)
@@ -192,6 +517,11 @@
/// before using.
const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
+ /// Returns the initialization pseudo-symbol, if any. This symbol will also
+ /// be present in the SymbolFlagsMap for this MaterializationResponsibility
+ /// object.
+ const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
+
/// 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
@@ -204,20 +534,53 @@
/// symbols must be ones covered by this MaterializationResponsibility
/// instance. Individual calls to this method may resolve a subset of the
/// symbols, but all symbols must have been resolved prior to calling emit.
- void notifyResolved(const SymbolMap &Symbols);
+ ///
+ /// This method will return an error if any symbols being resolved have been
+ /// moved to the error state due to the failure of a dependency. If this
+ /// method returns an error then clients should log it and call
+ /// failMaterialize. If no dependencies have been registered for the
+ /// symbols covered by this MaterializationResponsibiility then this method
+ /// is guaranteed to return Error::success() and can be wrapped with cantFail.
+ Error notifyResolved(const SymbolMap &Symbols);
/// Notifies the target JITDylib (and any pending queries on that JITDylib)
/// that all symbols covered by this MaterializationResponsibility instance
/// have been emitted.
- void notifyEmitted();
+ ///
+ /// This method will return an error if any symbols being resolved have been
+ /// moved to the error state due to the failure of a dependency. If this
+ /// method returns an error then clients should log it and call
+ /// failMaterialize. If no dependencies have been registered for the
+ /// symbols covered by this MaterializationResponsibiility then this method
+ /// is guaranteed to return Error::success() and can be wrapped with cantFail.
+ Error notifyEmitted();
- /// Adds new symbols to the JITDylib and this responsibility instance.
- /// JITDylib entries start out in the materializing state.
+ /// Attempt to claim responsibility for new definitions. This method can be
+ /// used to claim responsibility for symbols that are added to a
+ /// materialization unit during the compilation process (e.g. literal pool
+ /// symbols). Symbol linkage rules are the same as for symbols that are
+ /// defined up front: duplicate strong definitions will result in errors.
+ /// Duplicate weak definitions will be discarded (in which case they will
+ /// not be added to this responsibility instance).
///
/// 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);
+ Error defineMaterializing(SymbolFlagsMap SymbolFlags);
+
+ /// Define the given symbols as non-existent, removing it from the symbol
+ /// table and notifying any pending queries. Queries that lookup up the
+ /// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will
+ /// behave as if the symbol had not been matched in the first place. Queries
+ /// that required this symbol will fail with a missing symbol definition
+ /// error.
+ ///
+ /// This method is intended to support cleanup of special symbols like
+ /// initializer symbols: Queries using
+ /// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their
+ /// emission, and this method can be used to remove them from the JITDylib
+ /// once materialization is complete.
+ void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols);
/// Notify all not-yet-emitted covered by this MaterializationResponsibility
/// instance that an error has occurred.
@@ -231,13 +594,13 @@
/// 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);
+ Error 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,
- VModuleKey NewKey = VModuleKey());
+ Expected<std::unique_ptr<MaterializationResponsibility>>
+ delegate(const SymbolNameSet &Symbols);
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependencies);
@@ -248,12 +611,17 @@
private:
/// Create a MaterializationResponsibility for the given JITDylib and
/// initial symbols.
- MaterializationResponsibility(JITDylib &JD, SymbolFlagsMap SymbolFlags,
- VModuleKey K);
+ MaterializationResponsibility(JITDylibSP JD, SymbolFlagsMap SymbolFlags,
+ SymbolStringPtr InitSymbol)
+ : JD(std::move(JD)), SymbolFlags(std::move(SymbolFlags)),
+ InitSymbol(std::move(InitSymbol)) {
+ assert(this->JD && "Cannot initialize with null JITDylib");
+ assert(!this->SymbolFlags.empty() && "Materializing nothing?");
+ }
- JITDylib &JD;
+ JITDylibSP JD;
SymbolFlagsMap SymbolFlags;
- VModuleKey K;
+ SymbolStringPtr InitSymbol;
};
/// A MaterializationUnit represents a set of symbol definitions that can
@@ -265,9 +633,17 @@
/// is requested via the lookup method. The JITDylib will call discard if a
/// stronger definition is added or already present.
class MaterializationUnit {
+ friend class ExecutionSession;
+ friend class JITDylib;
+
public:
- MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, VModuleKey K)
- : SymbolFlags(std::move(InitalSymbolFlags)), K(std::move(K)) {}
+ MaterializationUnit(SymbolFlagsMap InitalSymbolFlags,
+ SymbolStringPtr InitSymbol)
+ : SymbolFlags(std::move(InitalSymbolFlags)),
+ InitSymbol(std::move(InitSymbol)) {
+ assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&
+ "If set, InitSymbol should appear in InitialSymbolFlags map");
+ }
virtual ~MaterializationUnit() {}
@@ -278,13 +654,14 @@
/// Return the set of symbols that this source provides.
const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
- /// Called by materialization dispatchers (see
- /// ExecutionSession::DispatchMaterializationFunction) to trigger
- /// materialization of this MaterializationUnit.
- void doMaterialize(JITDylib &JD) {
- materialize(MaterializationResponsibility(JD, std::move(SymbolFlags),
- std::move(K)));
- }
+ /// Returns the initialization symbol for this MaterializationUnit (if any).
+ const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
+
+ /// Implementations of this method should materialize all symbols
+ /// in the materialzation unit, except for those that have been
+ /// previously discarded.
+ virtual void
+ materialize(std::unique_ptr<MaterializationResponsibility> R) = 0;
/// Called by JITDylibs to notify MaterializationUnits that the given symbol
/// has been overridden.
@@ -295,16 +672,11 @@
protected:
SymbolFlagsMap SymbolFlags;
- VModuleKey K;
+ SymbolStringPtr InitSymbol;
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
@@ -312,21 +684,18 @@
virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
};
-using MaterializationUnitList =
- std::vector<std::unique_ptr<MaterializationUnit>>;
-
/// A MaterializationUnit implementation for pre-existing absolute symbols.
///
/// All symbols will be resolved and marked ready as soon as the unit is
/// materialized.
class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
public:
- AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K);
+ AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
StringRef getName() const override;
private:
- void materialize(MaterializationResponsibility R) override;
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
@@ -344,9 +713,9 @@
/// \endcode
///
inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
-absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) {
- return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
- std::move(Symbols), std::move(K));
+absoluteSymbols(SymbolMap Symbols) {
+ return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
+ std::move(Symbols));
}
/// A materialization unit for symbol aliases. Allows existing symbols to be
@@ -361,18 +730,19 @@
/// 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(JITDylib *SourceJD, bool MatchNonExported,
- SymbolAliasMap Aliases, VModuleKey K);
+ ReExportsMaterializationUnit(JITDylib *SourceJD,
+ JITDylibLookupFlags SourceJDLookupFlags,
+ SymbolAliasMap Aliases);
StringRef getName() const override;
private:
- void materialize(MaterializationResponsibility R) override;
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
JITDylib *SourceJD = nullptr;
- bool MatchNonExported = false;
+ JITDylibLookupFlags SourceJDLookupFlags;
SymbolAliasMap Aliases;
};
@@ -388,47 +758,26 @@
/// return Err;
/// \endcode
inline std::unique_ptr<ReExportsMaterializationUnit>
-symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
- return llvm::make_unique<ReExportsMaterializationUnit>(
- nullptr, true, std::move(Aliases), std::move(K));
+symbolAliases(SymbolAliasMap Aliases) {
+ return std::make_unique<ReExportsMaterializationUnit>(
+ nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
}
/// Create a materialization unit for re-exporting symbols from another JITDylib
/// with alternative names/flags.
-/// If MatchNonExported is true then non-exported symbols from SourceJD can be
-/// re-exported. If it is false, attempts to re-export a non-exported symbol
-/// will result in a "symbol not found" error.
+/// SourceJD will be searched using the given JITDylibLookupFlags.
inline std::unique_ptr<ReExportsMaterializationUnit>
reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
- bool MatchNonExported = false, VModuleKey K = VModuleKey()) {
- return llvm::make_unique<ReExportsMaterializationUnit>(
- &SourceJD, MatchNonExported, std::move(Aliases), std::move(K));
+ JITDylibLookupFlags SourceJDLookupFlags =
+ JITDylibLookupFlags::MatchExportedSymbolsOnly) {
+ return std::make_unique<ReExportsMaterializationUnit>(
+ &SourceJD, SourceJDLookupFlags, std::move(Aliases));
}
/// Build a SymbolAliasMap for the common case where you want to re-export
/// symbols from another JITDylib with the same linkage/flags.
Expected<SymbolAliasMap>
-buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
-
-/// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
-/// re-export a subset of the source JITDylib's symbols in the target.
-class ReexportsGenerator {
-public:
- using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
-
- /// Create a reexports generator. If an Allow predicate is passed, only
- /// symbols for which the predicate returns true will be reexported. If no
- /// Allow predicate is passed, all symbols will be exported.
- ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
- SymbolPredicate Allow = SymbolPredicate());
-
- Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
-
-private:
- JITDylib &SourceJD;
- bool MatchNonExported = false;
- SymbolPredicate Allow;
-};
+buildSimpleReexportsAAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
/// Represents the state that a symbol has reached during materialization.
enum class SymbolState : uint8_t {
@@ -436,6 +785,7 @@
NeverSearched, /// Added to the symbol table, never queried.
Materializing, /// Queried, materialization begun.
Resolved, /// Assigned address, still materializing.
+ Emitted, /// Emitted to memory, but waiting on transitive dependencies.
Ready = 0x3f /// Ready and safe for clients to access.
};
@@ -445,14 +795,16 @@
/// makes a callback when all symbols are available.
class AsynchronousSymbolQuery {
friend class ExecutionSession;
+ friend class InProgressFullLookupState;
friend class JITDylib;
friend class JITSymbolResolverAdapter;
+ friend class MaterializationResponsibility;
public:
/// Create a query for the given symbols. The NotifyComplete
/// callback will be called once all queried symbols reach the given
/// minimum state.
- AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
+ AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
SymbolState RequiredState,
SymbolsResolvedCallback NotifyComplete);
@@ -477,7 +829,7 @@
void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
- bool canStillFail();
+ void dropSymbol(const SymbolStringPtr &Name);
void handleFailed(Error Err);
@@ -490,19 +842,62 @@
SymbolState RequiredState;
};
+/// Wraps state for a lookup-in-progress.
+/// DefinitionGenerators can optionally take ownership of a LookupState object
+/// to suspend a lookup-in-progress while they search for definitions.
+class LookupState {
+ friend class OrcV2CAPIHelper;
+ friend class ExecutionSession;
+
+public:
+ LookupState();
+ LookupState(LookupState &&);
+ LookupState &operator=(LookupState &&);
+ ~LookupState();
+
+ /// Continue the lookup. This can be called by DefinitionGenerators
+ /// to re-start a captured query-application operation.
+ void continueLookup(Error Err);
+
+private:
+ LookupState(std::unique_ptr<InProgressLookupState> IPLS);
+
+ // For C API.
+ void reset(InProgressLookupState *IPLS);
+
+ std::unique_ptr<InProgressLookupState> IPLS;
+};
+
+/// Definition generators can be attached to JITDylibs to generate new
+/// definitions for otherwise unresolved symbols during lookup.
+class DefinitionGenerator {
+public:
+ virtual ~DefinitionGenerator();
+
+ /// DefinitionGenerators should override this method to insert new
+ /// definitions into the parent JITDylib. K specifies the kind of this
+ /// lookup. JD specifies the target JITDylib being searched, and
+ /// JDLookupFlags specifies whether the search should match against
+ /// hidden symbols. Finally, Symbols describes the set of unresolved
+ /// symbols and their associated lookup flags.
+ virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags,
+ const SymbolLookupSet &LookupSet) = 0;
+};
+
/// 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.
/// JITDylib state changes must be made via an ExecutionSession to guarantee
/// that they are synchronized with respect to other JITDylib operations.
-class JITDylib {
+class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
+ public jitlink::JITLinkDylib {
friend class AsynchronousSymbolQuery;
friend class ExecutionSession;
+ friend class Platform;
friend class MaterializationResponsibility;
public:
- using GeneratorFunction = std::function<Expected<SymbolNameSet>(
- JITDylib &Parent, const SymbolNameSet &Names)>;
using AsynchronousSymbolQuerySet =
std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
@@ -518,62 +913,88 @@
/// Get a reference to the ExecutionSession for this JITDylib.
ExecutionSession &getExecutionSession() const { return ES; }
- /// Set a definition generator. If set, whenever a symbol fails to resolve
- /// within this JITDylib, lookup and lookupFlags will pass the unresolved
- /// symbols set to the definition generator. The generator can optionally
- /// add a definition for the unresolved symbols to the dylib.
- void setGenerator(GeneratorFunction DefGenerator) {
- this->DefGenerator = std::move(DefGenerator);
- }
+ /// Calls remove on all trackers currently associated with this JITDylib.
+ /// Does not run static deinits.
+ ///
+ /// Note that removal happens outside the session lock, so new code may be
+ /// added concurrently while the clear is underway, and the newly added
+ /// code will *not* be cleared. Adding new code concurrently with a clear
+ /// is usually a bug and should be avoided.
+ Error clear();
- /// Set the search order to be used when fixing up definitions in JITDylib.
- /// This will replace the previous search order, and apply to any symbol
+ /// Get the default resource tracker for this JITDylib.
+ ResourceTrackerSP getDefaultResourceTracker();
+
+ /// Create a resource tracker for this JITDylib.
+ ResourceTrackerSP createResourceTracker();
+
+ /// Adds a definition generator to this JITDylib and returns a referenece to
+ /// it.
+ ///
+ /// When JITDylibs are searched during lookup, if no existing definition of
+ /// a symbol is found, then any generators that have been added are run (in
+ /// the order that they were added) to potentially generate a definition.
+ template <typename GeneratorT>
+ GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
+
+ /// Remove a definition generator from this JITDylib.
+ ///
+ /// The given generator must exist in this JITDylib's generators list (i.e.
+ /// have been added and not yet removed).
+ void removeGenerator(DefinitionGenerator &G);
+
+ /// Set the link order to be used when fixing up definitions in JITDylib.
+ /// This will replace the previous link order, and apply to any symbol
/// resolutions made for definitions in this JITDylib after the call to
- /// setSearchOrder (even if the definition itself was added before the
+ /// setLinkOrder (even if the definition itself was added before the
/// call).
///
- /// If SearchThisJITDylibFirst is set, which by default it is, then this
- /// JITDylib will add itself to the beginning of the SearchOrder (Clients
- /// should *not* put this JITDylib in the list in this case, to avoid
- /// redundant lookups).
+ /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib
+ /// will add itself to the beginning of the LinkOrder (Clients should not
+ /// put this JITDylib in the list in this case, to avoid redundant lookups).
///
- /// If SearchThisJITDylibFirst is false then the search order will be used as
- /// given. The main motivation for this feature is to support deliberate
+ /// If LinkAgainstThisJITDylibFirst is false then the link order will be used
+ /// as-is. The primary motivation for this feature is to support deliberate
/// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
/// the facade may resolve function names to stubs, and the stubs may compile
/// lazily by looking up symbols in this dylib. Adding the facade dylib
- /// as the first in the search order (instead of this dylib) ensures that
+ /// as the first in the link 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(JITDylibSearchList NewSearchOrder,
- bool SearchThisJITDylibFirst = true,
- bool MatchNonExportedInThisDylib = true);
+ void setLinkOrder(JITDylibSearchOrder NewSearchOrder,
+ bool LinkAgainstThisJITDylibFirst = true);
- /// Add the given JITDylib to the search order for definitions in this
+ /// Add the given JITDylib to the link order for definitions in this
/// JITDylib.
- void addToSearchOrder(JITDylib &JD, bool MatcNonExported = false);
+ void addToLinkOrder(JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags =
+ JITDylibLookupFlags::MatchExportedSymbolsOnly);
- /// Replace OldJD with NewJD in the search order if OldJD is present.
+ /// Replace OldJD with NewJD in the link order if OldJD is present.
/// Otherwise this operation is a no-op.
- void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD,
- bool MatchNonExported = false);
+ void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
+ JITDylibLookupFlags JDLookupFlags =
+ JITDylibLookupFlags::MatchExportedSymbolsOnly);
- /// Remove the given JITDylib from the search order for this JITDylib if it is
+ /// Remove the given JITDylib from the link order for this JITDylib if it is
/// present. Otherwise this operation is a no-op.
- void removeFromSearchOrder(JITDylib &JD);
+ void removeFromLinkOrder(JITDylib &JD);
- /// Do something with the search order (run under the session lock).
+ /// Do something with the link order (run under the session lock).
template <typename Func>
- auto withSearchOrderDo(Func &&F)
- -> decltype(F(std::declval<const JITDylibSearchList &>()));
+ auto withLinkOrderDo(Func &&F)
+ -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
/// Define all symbols provided by the materialization unit to be part of this
/// JITDylib.
///
+ /// If RT is not specified then the default resource tracker will be used.
+ ///
/// This overload always takes ownership of the MaterializationUnit. If any
/// errors occur, the MaterializationUnit consumed.
template <typename MaterializationUnitType>
- Error define(std::unique_ptr<MaterializationUnitType> &&MU);
+ Error define(std::unique_ptr<MaterializationUnitType> &&MU,
+ ResourceTrackerSP RT = nullptr);
/// Define all symbols provided by the materialization unit to be part of this
/// JITDylib.
@@ -583,7 +1004,8 @@
/// may allow the caller to modify the MaterializationUnit to correct the
/// issue, then re-call define.
template <typename MaterializationUnitType>
- Error define(std::unique_ptr<MaterializationUnitType> &MU);
+ Error define(std::unique_ptr<MaterializationUnitType> &MU,
+ ResourceTrackerSP RT = nullptr);
/// Tries to remove the given symbols.
///
@@ -597,52 +1019,61 @@
/// left unmodified (no symbols are removed).
Error remove(const SymbolNameSet &Names);
- /// Search the given JITDylib for the symbols in Symbols. If found, store
- /// the flags for each symbol in Flags. Returns any unresolved symbols.
- Expected<SymbolFlagsMap> lookupFlags(const SymbolNameSet &Names);
-
/// Dump current JITDylib state to OS.
void dump(raw_ostream &OS);
- /// FIXME: Remove this when we remove the old ORC layers.
- /// Search the given JITDylibs in order for the symbols in Symbols. Results
- /// (once they become available) will be returned via the given Query.
- ///
- /// If any symbol is not found then the unresolved symbols will be returned,
- /// 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.
- Expected<SymbolNameSet>
- legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names);
+ /// Returns the given JITDylibs and all of their transitive dependencies in
+ /// DFS order (based on linkage relationships). Each JITDylib will appear
+ /// only once.
+ static std::vector<JITDylibSP> getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
+
+ /// Returns the given JITDylibs and all of their transitive dependensies in
+ /// reverse DFS order (based on linkage relationships). Each JITDylib will
+ /// appear only once.
+ static std::vector<JITDylibSP>
+ getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
+
+ /// Return this JITDylib and its transitive dependencies in DFS order
+ /// based on linkage relationships.
+ std::vector<JITDylibSP> getDFSLinkOrder();
+
+ /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
+ /// based on linkage relationships.
+ std::vector<JITDylibSP> getReverseDFSLinkOrder();
private:
using AsynchronousSymbolQueryList =
std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
struct UnmaterializedInfo {
- UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
- : MU(std::move(MU)) {}
+ UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
+ ResourceTracker *RT)
+ : MU(std::move(MU)), RT(RT) {}
std::unique_ptr<MaterializationUnit> MU;
+ ResourceTracker *RT;
};
using UnmaterializedInfosMap =
DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
+ using UnmaterializedInfosList =
+ std::vector<std::shared_ptr<UnmaterializedInfo>>;
+
struct MaterializingInfo {
SymbolDependenceMap Dependants;
SymbolDependenceMap UnemittedDependencies;
- bool IsEmitted = false;
void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
void removeQuery(const AsynchronousSymbolQuery &Q);
AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
- AsynchronousSymbolQueryList takeAllQueries();
+ AsynchronousSymbolQueryList takeAllPendingQueries() {
+ return std::move(PendingQueries);
+ }
bool hasQueriesPending() const { return !PendingQueries.empty(); }
const AsynchronousSymbolQueryList &pendingQueries() const {
return PendingQueries;
}
-
private:
AsynchronousSymbolQueryList PendingQueries;
};
@@ -660,11 +1091,6 @@
JITSymbolFlags getFlags() const { return Flags; }
SymbolState getState() const { return static_cast<SymbolState>(State); }
- bool isInMaterializationPhase() const {
- return getState() == SymbolState::Materializing ||
- getState() == SymbolState::Resolved;
- }
-
bool hasMaterializerAttached() const { return MaterializerAttached; }
bool isPendingRemoval() const { return PendingRemoval; }
@@ -700,22 +1126,16 @@
JITDylib(ExecutionSession &ES, std::string Name);
+ ResourceTrackerSP getTracker(MaterializationResponsibility &MR);
+ std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
+ removeTracker(ResourceTracker &RT);
+
+ void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
+
Error defineImpl(MaterializationUnit &MU);
- Expected<SymbolNameSet> lookupFlagsImpl(SymbolFlagsMap &Flags,
- const SymbolNameSet &Names);
-
- Error lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
- SymbolNameSet &Unresolved, bool MatchNonExported,
- MaterializationUnitList &MUs);
-
- void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
- SymbolNameSet &Unresolved, bool MatchNonExported,
- MaterializationUnitList &MUs);
-
- bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
- std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
- SymbolNameSet &Unresolved);
+ void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
+ ResourceTracker &RT);
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);
@@ -724,86 +1144,156 @@
const SymbolStringPtr &DependantName,
MaterializingInfo &EmittedMI);
- Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
+ Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
- void replace(std::unique_ptr<MaterializationUnit> MU);
+ Error replace(MaterializationResponsibility &FromMR,
+ std::unique_ptr<MaterializationUnit> MU);
+
+ Expected<std::unique_ptr<MaterializationResponsibility>>
+ delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
+ SymbolStringPtr InitSymbol);
SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependants);
- void resolve(const SymbolMap &Resolved);
+ Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
- void emit(const SymbolFlagsMap &Emitted);
+ Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted);
- void notifyFailed(const SymbolNameSet &FailedSymbols);
+ void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
+
+ using FailedSymbolsWorklist =
+ std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
+
+ static std::pair<AsynchronousSymbolQuerySet,
+ std::shared_ptr<SymbolDependenceMap>>
+ failSymbols(FailedSymbolsWorklist);
ExecutionSession &ES;
std::string JITDylibName;
+ std::mutex GeneratorsMutex;
+ bool Open = true;
SymbolTable Symbols;
UnmaterializedInfosMap UnmaterializedInfos;
MaterializingInfosMap MaterializingInfos;
- GeneratorFunction DefGenerator;
- JITDylibSearchList SearchOrder;
+ std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
+ JITDylibSearchOrder LinkOrder;
+ ResourceTrackerSP DefaultTracker;
+
+ // Map trackers to sets of symbols tracked.
+ DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
+ DenseMap<MaterializationResponsibility *, ResourceTracker *> MRTrackers;
+};
+
+/// Platforms set up standard symbols and mediate interactions between dynamic
+/// initializers (e.g. C++ static constructors) and ExecutionSession state.
+/// Note that Platforms do not automatically run initializers: clients are still
+/// responsible for doing this.
+class Platform {
+public:
+ virtual ~Platform();
+
+ /// This method will be called outside the session lock each time a JITDylib
+ /// is created (unless it is created with EmptyJITDylib set) to allow the
+ /// Platform to install any JITDylib specific standard symbols (e.g
+ /// __dso_handle).
+ virtual Error setupJITDylib(JITDylib &JD) = 0;
+
+ /// This method will be called under the ExecutionSession lock each time a
+ /// MaterializationUnit is added to a JITDylib.
+ virtual Error notifyAdding(ResourceTracker &RT,
+ const MaterializationUnit &MU) = 0;
+
+ /// This method will be called under the ExecutionSession lock when a
+ /// ResourceTracker is removed.
+ virtual Error notifyRemoving(ResourceTracker &RT) = 0;
+
+ /// A utility function for looking up initializer symbols. Performs a blocking
+ /// lookup for the given symbols in each of the given JITDylibs.
+ static Expected<DenseMap<JITDylib *, SymbolMap>>
+ lookupInitSymbols(ExecutionSession &ES,
+ const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
};
/// An ExecutionSession represents a running JIT program.
class ExecutionSession {
- // FIXME: Remove this when we remove the old ORC layers.
+ friend class InProgressLookupFlagsState;
+ friend class InProgressFullLookupState;
friend class JITDylib;
+ friend class LookupState;
+ friend class MaterializationResponsibility;
+ friend class ResourceTracker;
public:
/// For reporting errors.
using ErrorReporter = std::function<void(Error)>;
/// For dispatching MaterializationUnit::materialize calls.
- using DispatchMaterializationFunction = std::function<void(
- JITDylib &JD, std::unique_ptr<MaterializationUnit> MU)>;
+ using DispatchMaterializationFunction =
+ std::function<void(std::unique_ptr<MaterializationUnit> MU,
+ std::unique_ptr<MaterializationResponsibility> MR)>;
/// Construct an ExecutionSession.
///
/// SymbolStringPools may be shared between ExecutionSessions.
ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
+ /// End the session. Closes all JITDylibs.
+ Error endSession();
+
/// Add a symbol name to the SymbolStringPool and return a pointer to it.
SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
/// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
+ /// Set the Platform for this ExecutionSession.
+ void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
+
+ /// Get the Platform for this session.
+ /// Will return null if no Platform has been set for this ExecutionSession.
+ Platform *getPlatform() { return P.get(); }
+
/// Run the given lambda with the session mutex locked.
- template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
+ template <typename Func> decltype(auto) runSessionLocked(Func &&F) {
std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
return F();
}
- /// Get the "main" JITDylib, which is created automatically on construction of
- /// the ExecutionSession.
- JITDylib &getMainJITDylib();
+ /// Register the given ResourceManager with this ExecutionSession.
+ /// Managers will be notified of events in reverse order of registration.
+ void registerResourceManager(ResourceManager &RM);
+
+ /// Deregister the given ResourceManager with this ExecutionSession.
+ /// Manager must have been previously registered.
+ void deregisterResourceManager(ResourceManager &RM);
/// Return a pointer to the "name" JITDylib.
/// Ownership of JITDylib remains within Execution Session
JITDylib *getJITDylibByName(StringRef Name);
+ /// Add a new bare JITDylib to this ExecutionSession.
+ ///
+ /// The JITDylib Name is required to be unique. Clients should verify that
+ /// names are not being re-used (E.g. by calling getJITDylibByName) if names
+ /// are based on user input.
+ ///
+ /// This call does not install any library code or symbols into the newly
+ /// created JITDylib. The client is responsible for all configuration.
+ JITDylib &createBareJITDylib(std::string Name);
+
/// Add a new JITDylib to this ExecutionSession.
///
/// The JITDylib Name is required to be unique. Clients should verify that
/// names are not being re-used (e.g. by calling getJITDylibByName) if names
/// are based on user input.
- JITDylib &createJITDylib(std::string Name,
- bool AddToMainDylibSearchOrder = true);
-
- /// Allocate a module key for a new module to add to the JIT.
- VModuleKey allocateVModule() {
- return runSessionLocked([this]() { return ++LastKey; });
- }
-
- /// Return a module key to the ExecutionSession so that it can be
- /// re-used. This should only be done once all resources associated
- /// with the original key have been released.
- void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
- }
+ ///
+ /// If a Platform is attached then Platform::setupJITDylib will be called to
+ /// install standard platform symbols (e.g. standard library interposes).
+ /// If no Platform is attached this call is equivalent to createBareJITDylib.
+ Expected<JITDylib &> createJITDylib(std::string Name);
/// Set the error reporter function.
ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
@@ -823,19 +1313,18 @@
return *this;
}
- void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
+ /// Search the given JITDylibs to find the flags associated with each of the
+ /// given symbols.
+ void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
+ SymbolLookupSet Symbols,
+ unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
- using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
- std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
+ /// Blocking version of lookupFlags.
+ Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
+ JITDylibSearchOrder SearchOrder,
+ SymbolLookupSet Symbols);
- /// A legacy lookup function for JITSymbolResolverAdapter.
- /// Do not use -- this will be removed soon.
- Expected<SymbolMap>
- legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
- SymbolState RequiredState,
- RegisterDependenciesFunction RegisterDependencies);
-
- /// Search the given JITDylib list for the given symbols.
+ /// Search the given JITDylibs for the given symbols.
///
/// SearchOrder lists the JITDylibs to search. For each dylib, the associated
/// boolean indicates whether the search should match against non-exported
@@ -854,8 +1343,9 @@
/// 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 JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
- SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete,
+ void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
+ SymbolLookupSet Symbols, SymbolState RequiredState,
+ SymbolsResolvedCallback NotifyComplete,
RegisterDependenciesFunction RegisterDependencies);
/// Blocking version of lookup above. Returns the resolved symbol map.
@@ -865,8 +1355,9 @@
/// 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 JITDylibSearchList &SearchOrder,
- const SymbolNameSet &Symbols,
+ Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
+ const SymbolLookupSet &Symbols,
+ LookupKind K = LookupKind::Static,
SymbolState RequiredState = SymbolState::Ready,
RegisterDependenciesFunction RegisterDependencies =
NoDependenciesToRegister);
@@ -874,30 +1365,31 @@
/// Convenience version of blocking lookup.
/// Searches each of the JITDylibs in the search order in turn for the given
/// symbol.
- Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchList &SearchOrder,
- SymbolStringPtr Symbol);
+ Expected<JITEvaluatedSymbol>
+ lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,
+ SymbolState RequiredState = SymbolState::Ready);
/// Convenience version of blocking lookup.
/// Searches each of the JITDylibs in the search order in turn for the given
/// symbol. The search will not find non-exported symbols.
- Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
- SymbolStringPtr Symbol);
+ Expected<JITEvaluatedSymbol>
+ lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,
+ SymbolState RequiredState = SymbolState::Ready);
/// Convenience version of blocking lookup.
/// Searches each of the JITDylibs in the search order in turn for the given
/// symbol. The search will not find non-exported symbols.
- Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
- StringRef Symbol);
+ Expected<JITEvaluatedSymbol>
+ lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,
+ SymbolState RequiredState = SymbolState::Ready);
/// Materialize the given unit.
- void dispatchMaterialization(JITDylib &JD,
- std::unique_ptr<MaterializationUnit> MU) {
- LLVM_DEBUG({
- runSessionLocked([&]() {
- dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n";
- });
- });
- DispatchMaterialization(JD, std::move(MU));
+ void
+ dispatchMaterialization(std::unique_ptr<MaterializationUnit> MU,
+ std::unique_ptr<MaterializationResponsibility> MR) {
+ assert(MU && "MU must be non-null");
+ DEBUG_WITH_TYPE("orc", dumpDispatchInfo(MR->getTargetJITDylib(), *MU));
+ DispatchMaterialization(std::move(MU), std::move(MR));
}
/// Dump the state of all the JITDylibs in this session.
@@ -908,84 +1400,290 @@
logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
}
- static void
- materializeOnCurrentThread(JITDylib &JD,
- std::unique_ptr<MaterializationUnit> MU) {
- MU->doMaterialize(JD);
+ static void materializeOnCurrentThread(
+ std::unique_ptr<MaterializationUnit> MU,
+ std::unique_ptr<MaterializationResponsibility> MR) {
+ MU->materialize(std::move(MR));
}
- void runOutstandingMUs();
+ void dispatchOutstandingMUs();
+
+ static std::unique_ptr<MaterializationResponsibility>
+ createMaterializationResponsibility(ResourceTracker &RT,
+ SymbolFlagsMap Symbols,
+ SymbolStringPtr InitSymbol) {
+ auto &JD = RT.getJITDylib();
+ std::unique_ptr<MaterializationResponsibility> MR(
+ new MaterializationResponsibility(&JD, std::move(Symbols),
+ std::move(InitSymbol)));
+ JD.MRTrackers[MR.get()] = &RT;
+ return MR;
+ }
+
+ Error removeResourceTracker(ResourceTracker &RT);
+ void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
+ void destroyResourceTracker(ResourceTracker &RT);
+
+ // State machine functions for query application..
+
+ /// IL_updateCandidatesFor is called to remove already-defined symbols that
+ /// match a given query from the set of candidate symbols to generate
+ /// definitions for (no need to generate a definition if one already exists).
+ Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
+ SymbolLookupSet &Candidates,
+ SymbolLookupSet *NonCandidates);
+
+ /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
+ /// definition generation. It is called when a lookup is performed, and again
+ /// each time that LookupState::continueLookup is called.
+ void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
+ Error Err);
+
+ /// OL_completeLookup is run once phase 1 successfully completes for a lookup
+ /// call. It attempts to attach the symbol to all symbol table entries and
+ /// collect all MaterializationUnits to dispatch. If this method fails then
+ /// all MaterializationUnits will be left un-materialized.
+ void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
+ std::shared_ptr<AsynchronousSymbolQuery> Q,
+ RegisterDependenciesFunction RegisterDependencies);
+
+ /// OL_completeLookupFlags is run once phase 1 successfully completes for a
+ /// lookupFlags call.
+ void OL_completeLookupFlags(
+ std::unique_ptr<InProgressLookupState> IPLS,
+ unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
+
+ // State machine functions for MaterializationResponsibility.
+ void OL_destroyMaterializationResponsibility(
+ MaterializationResponsibility &MR);
+ SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
+ Error OL_notifyResolved(MaterializationResponsibility &MR,
+ const SymbolMap &Symbols);
+ Error OL_notifyEmitted(MaterializationResponsibility &MR);
+ Error OL_defineMaterializing(MaterializationResponsibility &MR,
+ SymbolFlagsMap SymbolFlags);
+ void OL_notifyFailed(MaterializationResponsibility &MR);
+ Error OL_replace(MaterializationResponsibility &MR,
+ std::unique_ptr<MaterializationUnit> MU);
+ Expected<std::unique_ptr<MaterializationResponsibility>>
+ OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols);
+ void OL_addDependencies(MaterializationResponsibility &MR,
+ const SymbolStringPtr &Name,
+ const SymbolDependenceMap &Dependencies);
+ void OL_addDependenciesForAll(MaterializationResponsibility &MR,
+ const SymbolDependenceMap &Dependencies);
+
+#ifndef NDEBUG
+ void dumpDispatchInfo(JITDylib &JD, MaterializationUnit &MU);
+#endif // NDEBUG
mutable std::recursive_mutex SessionMutex;
+ bool SessionOpen = true;
std::shared_ptr<SymbolStringPool> SSP;
- VModuleKey LastKey = 0;
+ std::unique_ptr<Platform> P;
ErrorReporter ReportError = logErrorsToStdErr;
DispatchMaterializationFunction DispatchMaterialization =
materializeOnCurrentThread;
- std::vector<std::unique_ptr<JITDylib>> JDs;
+ std::vector<ResourceManager *> ResourceManagers;
+
+ std::vector<JITDylibSP> JDs;
// FIXME: Remove this (and runOutstandingMUs) once the linking layer works
// with callbacks from asynchronous queries.
mutable std::recursive_mutex OutstandingMUsMutex;
- std::vector<std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>>>
+ std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
+ std::unique_ptr<MaterializationResponsibility>>>
OutstandingMUs;
};
+inline ExecutionSession &MaterializationResponsibility::getExecutionSession() {
+ return JD->getExecutionSession();
+}
+
template <typename Func>
-auto JITDylib::withSearchOrderDo(Func &&F)
- -> decltype(F(std::declval<const JITDylibSearchList &>())) {
- return ES.runSessionLocked([&]() { return F(SearchOrder); });
-}
-
-template <typename MaterializationUnitType>
-Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
- assert(MU && "Can not define with a null MU");
- return ES.runSessionLocked([&, this]() -> Error {
- if (auto Err = defineImpl(*MU))
- return Err;
-
- /// defineImpl succeeded.
- auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
- for (auto &KV : UMI->MU->getSymbols())
- UnmaterializedInfos[KV.first] = UMI;
-
+Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const {
+ return JD->getExecutionSession().runSessionLocked([&]() -> Error {
+ auto I = JD->MRTrackers.find(this);
+ assert(I != JD->MRTrackers.end() && "No tracker for this MR");
+ if (I->second->isDefunct())
+ return make_error<ResourceTrackerDefunct>(I->second);
+ F(I->second->getKeyUnsafe());
return Error::success();
});
}
+template <typename GeneratorT>
+GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
+ auto &G = *DefGenerator;
+ std::lock_guard<std::mutex> Lock(GeneratorsMutex);
+ DefGenerators.push_back(std::move(DefGenerator));
+ return G;
+}
+
+template <typename Func>
+auto JITDylib::withLinkOrderDo(Func &&F)
+ -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
+ return ES.runSessionLocked([&]() { return F(LinkOrder); });
+}
+
template <typename MaterializationUnitType>
-Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
+Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
+ ResourceTrackerSP RT) {
assert(MU && "Can not define with a null MU");
+ if (MU->getSymbols().empty()) {
+ // Empty MUs are allowable but pathological, so issue a warning.
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for "
+ << getName() << "\n";
+ });
+ return Error::success();
+ } else
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Defining MU " << MU->getName() << " for " << getName()
+ << " (tracker: ";
+ if (RT == getDefaultResourceTracker())
+ dbgs() << "default)";
+ else if (RT)
+ dbgs() << RT.get() << ")\n";
+ else
+ dbgs() << "0x0, default will be used)\n";
+ });
+
return ES.runSessionLocked([&, this]() -> Error {
if (auto Err = defineImpl(*MU))
return Err;
- /// defineImpl succeeded.
- auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
- for (auto &KV : UMI->MU->getSymbols())
- UnmaterializedInfos[KV.first] = UMI;
+ if (!RT)
+ RT = getDefaultResourceTracker();
+ if (auto *P = ES.getPlatform()) {
+ if (auto Err = P->notifyAdding(*RT, *MU))
+ return Err;
+ }
+
+ installMaterializationUnit(std::move(MU), *RT);
return Error::success();
});
}
-/// Mangles symbol names then uniques them in the context of an
-/// ExecutionSession.
-class MangleAndInterner {
+template <typename MaterializationUnitType>
+Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
+ ResourceTrackerSP RT) {
+ assert(MU && "Can not define with a null MU");
+
+ if (MU->getSymbols().empty()) {
+ // Empty MUs are allowable but pathological, so issue a warning.
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName()
+ << "\n";
+ });
+ return Error::success();
+ } else
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Defining MU " << MU->getName() << " for " << getName()
+ << " (tracker: ";
+ if (RT == getDefaultResourceTracker())
+ dbgs() << "default)";
+ else if (RT)
+ dbgs() << RT.get() << ")\n";
+ else
+ dbgs() << "0x0, default will be used)\n";
+ });
+
+ return ES.runSessionLocked([&, this]() -> Error {
+ if (auto Err = defineImpl(*MU))
+ return Err;
+
+ if (!RT)
+ RT = getDefaultResourceTracker();
+
+ if (auto *P = ES.getPlatform()) {
+ if (auto Err = P->notifyAdding(*RT, *MU))
+ return Err;
+ }
+
+ installMaterializationUnit(std::move(MU), *RT);
+ return Error::success();
+ });
+}
+
+/// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
+/// re-export a subset of the source JITDylib's symbols in the target.
+class ReexportsGenerator : public DefinitionGenerator {
public:
- MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
- SymbolStringPtr operator()(StringRef Name);
+ using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+
+ /// Create a reexports generator. If an Allow predicate is passed, only
+ /// symbols for which the predicate returns true will be reexported. If no
+ /// Allow predicate is passed, all symbols will be exported.
+ ReexportsGenerator(JITDylib &SourceJD,
+ JITDylibLookupFlags SourceJDLookupFlags,
+ SymbolPredicate Allow = SymbolPredicate());
+
+ Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags,
+ const SymbolLookupSet &LookupSet) override;
private:
- ExecutionSession &ES;
- const DataLayout &DL;
+ JITDylib &SourceJD;
+ JITDylibLookupFlags SourceJDLookupFlags;
+ SymbolPredicate Allow;
};
+// --------------- IMPLEMENTATION --------------
+// Implementations for inline functions/methods.
+// ---------------------------------------------
+
+inline MaterializationResponsibility::~MaterializationResponsibility() {
+ JD->getExecutionSession().OL_destroyMaterializationResponsibility(*this);
+}
+
+inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
+ return JD->getExecutionSession().OL_getRequestedSymbols(*this);
+}
+
+inline Error MaterializationResponsibility::notifyResolved(
+ const SymbolMap &Symbols) {
+ return JD->getExecutionSession().OL_notifyResolved(*this, Symbols);
+}
+
+inline Error MaterializationResponsibility::notifyEmitted() {
+ return JD->getExecutionSession().OL_notifyEmitted(*this);
+}
+
+inline Error MaterializationResponsibility::defineMaterializing(
+ SymbolFlagsMap SymbolFlags) {
+ return JD->getExecutionSession().OL_defineMaterializing(
+ *this, std::move(SymbolFlags));
+}
+
+inline void MaterializationResponsibility::failMaterialization() {
+ JD->getExecutionSession().OL_notifyFailed(*this);
+}
+
+inline Error MaterializationResponsibility::replace(
+ std::unique_ptr<MaterializationUnit> MU) {
+ return JD->getExecutionSession().OL_replace(*this, std::move(MU));
+}
+
+inline Expected<std::unique_ptr<MaterializationResponsibility>>
+MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
+ return JD->getExecutionSession().OL_delegate(*this, Symbols);
+}
+
+inline void MaterializationResponsibility::addDependencies(
+ const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
+ JD->getExecutionSession().OL_addDependencies(*this, Name, Dependencies);
+}
+
+inline void MaterializationResponsibility::addDependenciesForAll(
+ const SymbolDependenceMap &Dependencies) {
+ JD->getExecutionSession().OL_addDependenciesForAll(*this, Dependencies);
+}
+
} // End namespace orc
} // End namespace llvm
-#undef DEBUG_TYPE // "orc"
-
#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/DebugUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/DebugUtils.h
new file mode 100644
index 0000000..4b4472e
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/DebugUtils.h
@@ -0,0 +1,130 @@
+//===----- DebugUtils.h - Utilities for debugging ORC JITs ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for debugging ORC-based JITs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_DEBUGUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_DEBUGUTILS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+
+class MemoryBuffer;
+
+namespace orc {
+
+// --raw_ostream operators for ORC types--
+
+/// Render a SymbolStringPtr.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
+
+/// Render a SymbolNameSet.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
+
+/// Render a SymbolNameVector.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols);
+
+/// Render an array of SymbolStringPtrs.
+raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols);
+
+/// Render JITSymbolFlags.
+raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags);
+
+/// Render a SymbolFlagsMap entry.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV);
+
+/// Render a SymbolMap entry.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV);
+
+/// Render a SymbolFlagsMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
+
+/// Render a SymbolMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
+
+/// Render a SymbolDependenceMap entry.
+raw_ostream &operator<<(raw_ostream &OS,
+ const SymbolDependenceMap::value_type &KV);
+
+/// Render a SymbolDependendeMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
+
+/// Render a MaterializationUnit.
+raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
+
+//// Render a JITDylibLookupFlags instance.
+raw_ostream &operator<<(raw_ostream &OS,
+ const JITDylibLookupFlags &JDLookupFlags);
+
+/// Rendar a SymbolLookupFlags instance.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags);
+
+/// Render a JITDylibLookupFlags instance.
+raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K);
+
+/// Render a SymbolLookupSet entry.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet::value_type &KV);
+
+/// Render a SymbolLookupSet.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet);
+
+/// Render a JITDylibSearchOrder.
+raw_ostream &operator<<(raw_ostream &OS,
+ const JITDylibSearchOrder &SearchOrder);
+
+/// Render a SymbolAliasMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases);
+
+/// Render a SymbolState.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S);
+
+/// Render a LookupKind.
+raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K);
+
+/// A function object that can be used as an ObjectTransformLayer transform
+/// to dump object files to disk at a specified path.
+class DumpObjects {
+public:
+ /// Construct a DumpObjects transform that will dump objects to disk.
+ ///
+ /// @param DumpDir specifies the path to write dumped objects to. DumpDir may
+ /// be empty, in which case files will be dumped to the working directory. If
+ /// DumpDir is non-empty then any trailing separators will be discarded.
+ ///
+ /// @param IdentifierOverride specifies a file name stem to use when dumping
+ /// objects. If empty, each MemoryBuffer's identifier will be used (with a .o
+ /// suffix added if not already present). If an identifier override is
+ /// supplied it will be used instead (since all buffers will use the same
+ /// identifier, the resulting files will be named <ident>.o, <ident>.2.o,
+ /// <ident>.3.o, and so on). IdentifierOverride should not contain an
+ /// extension, as a .o suffix will be added by DumpObjects.
+ DumpObjects(std::string DumpDir = "", std::string IdentifierOverride = "");
+
+ /// Dumps the given buffer to disk.
+ Expected<std::unique_ptr<MemoryBuffer>>
+ operator()(std::unique_ptr<MemoryBuffer> Obj);
+
+private:
+ StringRef getBufferIdentifier(MemoryBuffer &B);
+ std::string DumpDir;
+ std::string IdentifierOverride;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_DEBUGUTILS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index ae3ab8c..1dc2af4 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -17,8 +17,10 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/Object/Archive.h"
#include "llvm/Support/DynamicLibrary.h"
#include <algorithm>
#include <cstdint>
@@ -37,6 +39,8 @@
namespace orc {
+class ObjectLayer;
+
/// This iterator provides a convenient way to iterate over the elements
/// of an llvm.global_ctors/llvm.global_dtors instance.
///
@@ -90,44 +94,53 @@
/// array.
iterator_range<CtorDtorIterator> getDestructors(const Module &M);
-/// Convenience class for recording constructor/destructor names for
-/// later execution.
-template <typename JITLayerT>
-class LegacyCtorDtorRunner {
+/// This iterator provides a convenient way to iterate over GlobalValues that
+/// have initialization effects.
+class StaticInitGVIterator {
public:
- /// Construct a CtorDtorRunner for the given range using the given
- /// name mangling function.
- LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K)
- : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
+ StaticInitGVIterator() = default;
- /// Run the recorded constructors/destructors through the given JIT
- /// layer.
- Error runViaLayer(JITLayerT &JITLayer) const {
- using CtorDtorTy = void (*)();
-
- for (const auto &CtorDtorName : CtorDtorNames) {
- if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
- if (auto AddrOrErr = CtorDtorSym.getAddress()) {
- CtorDtorTy CtorDtor =
- reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
- CtorDtor();
- } else
- return AddrOrErr.takeError();
- } else {
- if (auto Err = CtorDtorSym.takeError())
- return Err;
- else
- return make_error<JITSymbolNotFound>(CtorDtorName);
- }
- }
- return Error::success();
+ StaticInitGVIterator(Module &M)
+ : I(M.global_values().begin()), E(M.global_values().end()),
+ ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) {
+ if (I != E) {
+ if (!isStaticInitGlobal(*I))
+ moveToNextStaticInitGlobal();
+ } else
+ I = E = Module::global_value_iterator();
}
+ bool operator==(const StaticInitGVIterator &O) const { return I == O.I; }
+ bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; }
+
+ StaticInitGVIterator &operator++() {
+ assert(I != E && "Increment past end of range");
+ moveToNextStaticInitGlobal();
+ return *this;
+ }
+
+ GlobalValue &operator*() { return *I; }
+
private:
- std::vector<std::string> CtorDtorNames;
- orc::VModuleKey K;
+ bool isStaticInitGlobal(GlobalValue &GV);
+ void moveToNextStaticInitGlobal() {
+ ++I;
+ while (I != E && !isStaticInitGlobal(*I))
+ ++I;
+ if (I == E)
+ I = E = Module::global_value_iterator();
+ }
+
+ Module::global_value_iterator I, E;
+ Triple::ObjectFormatType ObjFmt;
};
+/// Create an iterator range over the GlobalValues that contribute to static
+/// initialization.
+inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) {
+ return make_range(StaticInitGVIterator(M), StaticInitGVIterator());
+}
+
class CtorDtorRunner {
public:
CtorDtorRunner(JITDylib &JD) : JD(JD) {}
@@ -176,44 +189,35 @@
void *DSOHandle);
};
-class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
-public:
- /// Create a runtime-overrides class.
- template <typename MangleFtorT>
- LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
- addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
- addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
- }
-
- /// Search overrided symbols.
- JITEvaluatedSymbol searchOverrides(const std::string &Name) {
- auto I = CXXRuntimeOverrides.find(Name);
- if (I != CXXRuntimeOverrides.end())
- return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported);
- return nullptr;
- }
-
-private:
- void addOverride(const std::string &Name, JITTargetAddress Addr) {
- CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
- }
-
- StringMap<JITTargetAddress> CXXRuntimeOverrides;
-};
-
class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
public:
Error enable(JITDylib &JD, MangleAndInterner &Mangler);
};
+/// An interface for Itanium __cxa_atexit interposer implementations.
+class ItaniumCXAAtExitSupport {
+public:
+ struct AtExitRecord {
+ void (*F)(void *);
+ void *Ctx;
+ };
+
+ void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle);
+ void runAtExits(void *DSOHandle);
+
+private:
+ std::mutex AtExitsMutex;
+ DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords;
+};
+
/// A utility class to expose symbols found via dlsym to the JIT.
///
/// If an instance of this class is attached to a JITDylib as a fallback
/// definition generator, then any symbol found in the given DynamicLibrary that
/// passes the 'Allow' predicate will be added to the JITDylib.
-class DynamicLibrarySearchGenerator {
+class DynamicLibrarySearchGenerator : public DefinitionGenerator {
public:
- using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+ using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>;
/// Create a DynamicLibrarySearchGenerator that searches for symbols in the
/// given sys::DynamicLibrary.
@@ -227,19 +231,21 @@
/// Permanently loads the library at the given path and, on success, returns
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
/// in the library. On failure returns the reason the library failed to load.
- static Expected<DynamicLibrarySearchGenerator>
+ static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
Load(const char *FileName, char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate());
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
/// the current process.
- static Expected<DynamicLibrarySearchGenerator>
+ static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
GetForCurrentProcess(char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate()) {
return Load(nullptr, GlobalPrefix, std::move(Allow));
}
- Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names);
+ Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags,
+ const SymbolLookupSet &Symbols) override;
private:
sys::DynamicLibrary Dylib;
@@ -247,6 +253,48 @@
char GlobalPrefix;
};
+/// A utility class to expose symbols from a static library.
+///
+/// If an instance of this class is attached to a JITDylib as a fallback
+/// definition generator, then any symbol found in the archive will result in
+/// the containing object being added to the JITDylib.
+class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
+public:
+ /// Try to create a StaticLibraryDefinitionGenerator from the given path.
+ ///
+ /// This call will succeed if the file at the given path is a static library
+ /// is a valid archive, otherwise it will return an error.
+ static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+ Load(ObjectLayer &L, const char *FileName);
+
+ /// Try to create a StaticLibraryDefinitionGenerator from the given path.
+ ///
+ /// This call will succeed if the file at the given path is a static library
+ /// or a MachO universal binary containing a static library that is compatible
+ /// with the given triple. Otherwise it will return an error.
+ static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+ Load(ObjectLayer &L, const char *FileName, const Triple &TT);
+
+ /// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
+ /// This call will succeed if the buffer contains a valid archive, otherwise
+ /// it will return an error.
+ static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+ Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
+
+ Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags,
+ const SymbolLookupSet &Symbols) override;
+
+private:
+ StaticLibraryDefinitionGenerator(ObjectLayer &L,
+ std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+ Error &Err);
+
+ ObjectLayer &L;
+ std::unique_ptr<MemoryBuffer> ArchiveBuffer;
+ std::unique_ptr<object::Archive> Archive;
+};
+
} // end namespace orc
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
deleted file mode 100644
index a4e43d4..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===- GlobalMappingLayer.h - Run all IR through a functor ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Convenience layer for injecting symbols that will appear in calls to
-// findSymbol.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H
-#define LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H
-
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include <map>
-#include <memory>
-#include <string>
-
-namespace llvm {
-
-class Module;
-class JITSymbolResolver;
-
-namespace orc {
-
-/// 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
-/// mappings into the JIT. Beware, however: symbols within a single IR module or
-/// object file will still resolve locally (via RuntimeDyld's symbol table) -
-/// such internal references cannot be overriden via this layer.
-template <typename BaseLayerT>
-class GlobalMappingLayer {
-public:
-
- /// Handle to an added module.
- using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
-
- /// Construct an GlobalMappingLayer with the given BaseLayer
- GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
-
- /// Add the given module to the JIT.
- /// @return A handle for the added modules.
- Expected<ModuleHandleT>
- addModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- return BaseLayer.addModule(std::move(M), std::move(Resolver));
- }
-
- /// Remove the module set associated with the handle H.
- Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
-
- /// Manually set the address to return for the given symbol.
- void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
- SymbolTable[Name] = Addr;
- }
-
- /// Remove the given symbol from the global mapping.
- void eraseGlobalMapping(const std::string &Name) {
- SymbolTable.erase(Name);
- }
-
- /// 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
- /// table then this call will be passed through to the base layer.
- ///
- /// @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.
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- auto I = SymbolTable.find(Name);
- if (I != SymbolTable.end())
- return JITSymbol(I->second, JITSymbolFlags::Exported);
- return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
- }
-
- /// 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.
- /// @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 is found in the
- /// given module.
- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
- bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
- }
-
- /// 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) {
- return BaseLayer.emitAndFinalize(H);
- }
-
-private:
- BaseLayerT &BaseLayer;
- std::map<std::string, JITTargetAddress> SymbolTable;
-};
-
-} // end namespace orc
-} // end namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index ecff09b..f8fdb17 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -29,101 +29,44 @@
class IRCompileLayer : public IRLayer {
public:
- using CompileFunction =
- std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>;
+ class IRCompiler {
+ public:
+ IRCompiler(IRSymbolMapper::ManglingOptions MO) : MO(std::move(MO)) {}
+ virtual ~IRCompiler();
+ const IRSymbolMapper::ManglingOptions &getManglingOptions() const {
+ return MO;
+ }
+ virtual Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) = 0;
- using NotifyCompiledFunction =
- std::function<void(VModuleKey K, ThreadSafeModule TSM)>;
+ protected:
+ IRSymbolMapper::ManglingOptions &manglingOptions() { return MO; }
+
+ private:
+ IRSymbolMapper::ManglingOptions MO;
+ };
+
+ using NotifyCompiledFunction = std::function<void(
+ MaterializationResponsibility &R, ThreadSafeModule TSM)>;
IRCompileLayer(ExecutionSession &ES, ObjectLayer &BaseLayer,
- CompileFunction Compile);
+ std::unique_ptr<IRCompiler> Compile);
+
+ IRCompiler &getCompiler() { return *Compile; }
void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled);
- void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
+ ThreadSafeModule TSM) override;
private:
mutable std::mutex IRLayerMutex;
ObjectLayer &BaseLayer;
- CompileFunction Compile;
+ std::unique_ptr<IRCompiler> Compile;
+ const IRSymbolMapper::ManglingOptions *ManglingOpts;
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
-/// implement the object layer concept.
-template <typename BaseLayerT, typename CompileFtor>
-class LegacyIRCompileLayer {
-public:
- /// Callback type for notifications when modules are compiled.
- using NotifyCompiledCallback =
- std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
-
- /// Construct an LegacyIRCompileLayer with the given BaseLayer, which must
- /// implement the ObjectLayer concept.
- LegacyIRCompileLayer(
- BaseLayerT &BaseLayer, CompileFtor Compile,
- NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback())
- : BaseLayer(BaseLayer), Compile(std::move(Compile)),
- NotifyCompiled(std::move(NotifyCompiled)) {}
-
- /// Get a reference to the compiler functor.
- CompileFtor& getCompiler() { return Compile; }
-
- /// (Re)set the NotifyCompiled callback.
- void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) {
- this->NotifyCompiled = std::move(NotifyCompiled);
- }
-
- /// 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)))
- return Err;
- if (NotifyCompiled)
- NotifyCompiled(std::move(K), std::move(M));
- return Error::success();
- }
-
- /// Remove the module associated with the VModuleKey K.
- Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); }
-
- /// 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.
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
- }
-
- /// 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.
- /// @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 is found in the
- /// given module.
- JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
- }
-
- /// 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); }
-
-private:
- BaseLayerT &BaseLayer;
- CompileFtor Compile;
- NotifyCompiledCallback NotifyCompiled;
-};
-
} // end namespace orc
-
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
index 8890a57..66966a0 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -13,6 +13,7 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
+#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <memory>
@@ -22,10 +23,13 @@
class Module;
namespace orc {
+/// A layer that applies a transform to emitted modules.
+/// The transform function is responsible for locking the ThreadSafeContext
+/// before operating on the module.
class IRTransformLayer : public IRLayer {
public:
- using TransformFunction = std::function<Expected<ThreadSafeModule>(
- ThreadSafeModule, const MaterializationResponsibility &R)>;
+ using TransformFunction = unique_function<Expected<ThreadSafeModule>(
+ ThreadSafeModule, MaterializationResponsibility &R)>;
IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer,
TransformFunction Transform = identityTransform);
@@ -34,11 +38,11 @@
this->Transform = std::move(Transform);
}
- void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
+ ThreadSafeModule TSM) override;
- static ThreadSafeModule
- identityTransform(ThreadSafeModule TSM,
- const MaterializationResponsibility &R) {
+ static ThreadSafeModule identityTransform(ThreadSafeModule TSM,
+ MaterializationResponsibility &R) {
return TSM;
}
@@ -47,67 +51,6 @@
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.
-template <typename BaseLayerT, typename TransformFtor>
-class LegacyIRTransformLayer {
-public:
-
- /// Construct an LegacyIRTransformLayer with the given BaseLayer
- LegacyIRTransformLayer(BaseLayerT &BaseLayer,
- TransformFtor Transform = TransformFtor())
- : BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
-
- /// 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.
- Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
- return BaseLayer.addModule(std::move(K), Transform(std::move(M)));
- }
-
- /// Remove the module associated with the VModuleKey K.
- Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); }
-
- /// 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.
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
- }
-
- /// 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.
- /// @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 is found in the
- /// given module.
- JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
- }
-
- /// 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); }
-
- /// Access the transform functor directly.
- TransformFtor& getTransform() { return Transform; }
-
- /// Access the mumate functor directly.
- const TransformFtor& getTransform() const { return Transform; }
-
-private:
- BaseLayerT &BaseLayer;
- TransformFtor Transform;
-};
-
} // end namespace orc
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index a7ed537..78e3cee 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -15,9 +15,9 @@
#include "llvm/ADT/StringMap.h"
#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/OrcABISupport.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Process.h"
@@ -26,6 +26,7 @@
#include <cassert>
#include <cstdint>
#include <functional>
+#include <future>
#include <map>
#include <memory>
#include <system_error>
@@ -42,6 +43,7 @@
class Module;
class PointerType;
class Triple;
+class Twine;
class Value;
namespace orc {
@@ -53,41 +55,19 @@
/// are used by various ORC APIs to support lazy compilation
class TrampolinePool {
public:
- virtual ~TrampolinePool() {}
+ using NotifyLandingResolvedFunction =
+ unique_function<void(JITTargetAddress) const>;
+
+ using ResolveLandingFunction = unique_function<void(
+ JITTargetAddress TrampolineAddr,
+ NotifyLandingResolvedFunction OnLandingResolved) const>;
+
+ virtual ~TrampolinePool();
/// Get an available trampoline address.
/// Returns an error if no trampoline can be created.
- virtual Expected<JITTargetAddress> getTrampoline() = 0;
-
-private:
- virtual void anchor();
-};
-
-/// A trampoline pool for trampolines within the current process.
-template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
-public:
- using GetTrampolineLandingFunction =
- std::function<JITTargetAddress(JITTargetAddress TrampolineAddr)>;
-
- /// Creates a LocalTrampolinePool with the given RunCallback function.
- /// Returns an error if this function is unable to correctly allocate, write
- /// and protect the resolver code block.
- static Expected<std::unique_ptr<LocalTrampolinePool>>
- Create(GetTrampolineLandingFunction GetTrampolineLanding) {
- Error Err = Error::success();
-
- auto LTP = std::unique_ptr<LocalTrampolinePool>(
- new LocalTrampolinePool(std::move(GetTrampolineLanding), Err));
-
- if (Err)
- return std::move(Err);
- return std::move(LTP);
- }
-
- /// Get a free trampoline. Returns an error if one can not be provide (e.g.
- /// because the pool is empty and can not be grown).
- Expected<JITTargetAddress> getTrampoline() override {
- std::lock_guard<std::mutex> Lock(LTPMutex);
+ Expected<JITTargetAddress> getTrampoline() {
+ std::lock_guard<std::mutex> Lock(TPMutex);
if (AvailableTrampolines.empty()) {
if (auto Err = grow())
return std::move(Err);
@@ -100,21 +80,52 @@
/// Returns the given trampoline to the pool for re-use.
void releaseTrampoline(JITTargetAddress TrampolineAddr) {
- std::lock_guard<std::mutex> Lock(LTPMutex);
+ std::lock_guard<std::mutex> Lock(TPMutex);
AvailableTrampolines.push_back(TrampolineAddr);
}
+protected:
+ virtual Error grow() = 0;
+
+ std::mutex TPMutex;
+ std::vector<JITTargetAddress> AvailableTrampolines;
+};
+
+/// A trampoline pool for trampolines within the current process.
+template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
+public:
+ /// Creates a LocalTrampolinePool with the given RunCallback function.
+ /// Returns an error if this function is unable to correctly allocate, write
+ /// and protect the resolver code block.
+ static Expected<std::unique_ptr<LocalTrampolinePool>>
+ Create(ResolveLandingFunction ResolveLanding) {
+ Error Err = Error::success();
+
+ auto LTP = std::unique_ptr<LocalTrampolinePool>(
+ new LocalTrampolinePool(std::move(ResolveLanding), Err));
+
+ if (Err)
+ return std::move(Err);
+ return std::move(LTP);
+ }
+
private:
static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
LocalTrampolinePool<ORCABI> *TrampolinePool =
static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
- return TrampolinePool->GetTrampolineLanding(static_cast<JITTargetAddress>(
- reinterpret_cast<uintptr_t>(TrampolineId)));
+
+ std::promise<JITTargetAddress> LandingAddressP;
+ auto LandingAddressF = LandingAddressP.get_future();
+
+ TrampolinePool->ResolveLanding(pointerToJITTargetAddress(TrampolineId),
+ [&](JITTargetAddress LandingAddress) {
+ LandingAddressP.set_value(LandingAddress);
+ });
+ return LandingAddressF.get();
}
- LocalTrampolinePool(GetTrampolineLandingFunction GetTrampolineLanding,
- Error &Err)
- : GetTrampolineLanding(std::move(GetTrampolineLanding)) {
+ LocalTrampolinePool(ResolveLandingFunction ResolveLanding, Error &Err)
+ : ResolveLanding(std::move(ResolveLanding)) {
ErrorAsOutParameter _(&Err);
@@ -128,8 +139,10 @@
return;
}
- ORCABI::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
- &reenter, this);
+ ORCABI::writeResolverCode(static_cast<char *>(ResolverBlock.base()),
+ pointerToJITTargetAddress(ResolverBlock.base()),
+ pointerToJITTargetAddress(&reenter),
+ pointerToJITTargetAddress(this));
EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
sys::Memory::MF_READ |
@@ -140,8 +153,8 @@
}
}
- Error grow() {
- assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
+ Error grow() override {
+ assert(AvailableTrampolines.empty() && "Growing prematurely?");
std::error_code EC;
auto TrampolineBlock =
@@ -155,14 +168,14 @@
(sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) /
ORCABI::TrampolineSize;
- uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
- ORCABI::writeTrampolines(TrampolineMem, ResolverBlock.base(),
- NumTrampolines);
+ char *TrampolineMem = static_cast<char *>(TrampolineBlock.base());
+ ORCABI::writeTrampolines(
+ TrampolineMem, pointerToJITTargetAddress(TrampolineMem),
+ pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines);
for (unsigned I = 0; I < NumTrampolines; ++I)
- this->AvailableTrampolines.push_back(
- static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(
- TrampolineMem + (I * ORCABI::TrampolineSize))));
+ AvailableTrampolines.push_back(pointerToJITTargetAddress(
+ TrampolineMem + (I * ORCABI::TrampolineSize)));
if (auto EC = sys::Memory::protectMappedMemory(
TrampolineBlock.getMemoryBlock(),
@@ -173,12 +186,10 @@
return Error::success();
}
- GetTrampolineLandingFunction GetTrampolineLanding;
+ ResolveLandingFunction ResolveLanding;
- std::mutex LTPMutex;
sys::OwningMemoryBlock ResolverBlock;
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
- std::vector<JITTargetAddress> AvailableTrampolines;
};
/// Target-independent base class for compile callback management.
@@ -201,7 +212,7 @@
ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress)
: TP(std::move(TP)), ES(ES),
- CallbacksJD(ES.createJITDylib("<Callbacks>")),
+ CallbacksJD(ES.createBareJITDylib("<Callbacks>")),
ErrorHandlerAddress(ErrorHandlerAddress) {}
void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
@@ -241,10 +252,14 @@
JITTargetAddress ErrorHandlerAddress,
Error &Err)
: JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
+ using NotifyLandingResolvedFunction =
+ TrampolinePool::NotifyLandingResolvedFunction;
+
ErrorAsOutParameter _(&Err);
auto TP = LocalTrampolinePool<ORCABI>::Create(
- [this](JITTargetAddress TrampolineAddr) {
- return executeCompileCallback(TrampolineAddr);
+ [this](JITTargetAddress TrampolineAddr,
+ NotifyLandingResolvedFunction NotifyLandingResolved) {
+ NotifyLandingResolved(executeCompileCallback(TrampolineAddr));
});
if (!TP) {
@@ -287,6 +302,61 @@
virtual void anchor();
};
+template <typename ORCABI> class LocalIndirectStubsInfo {
+public:
+ LocalIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
+ : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
+
+ static Expected<LocalIndirectStubsInfo> create(unsigned MinStubs,
+ unsigned PageSize) {
+ auto ISAS = getIndirectStubsBlockSizes<ORCABI>(MinStubs, PageSize);
+
+ assert((ISAS.StubBytes % PageSize == 0) &&
+ "StubBytes is not a page size multiple");
+ uint64_t PointerAlloc = alignTo(ISAS.PointerBytes, PageSize);
+
+ // Allocate memory for stubs and pointers in one call.
+ std::error_code EC;
+ auto StubsAndPtrsMem =
+ sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
+ ISAS.StubBytes + PointerAlloc, nullptr,
+ sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
+ if (EC)
+ return errorCodeToError(EC);
+
+ sys::MemoryBlock StubsBlock(StubsAndPtrsMem.base(), ISAS.StubBytes);
+ auto StubsBlockMem = static_cast<char *>(StubsAndPtrsMem.base());
+ auto PtrBlockAddress =
+ pointerToJITTargetAddress(StubsBlockMem) + ISAS.StubBytes;
+
+ ORCABI::writeIndirectStubsBlock(StubsBlockMem,
+ pointerToJITTargetAddress(StubsBlockMem),
+ PtrBlockAddress, ISAS.NumStubs);
+
+ if (auto EC = sys::Memory::protectMappedMemory(
+ StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
+ return errorCodeToError(EC);
+
+ return LocalIndirectStubsInfo(ISAS.NumStubs, std::move(StubsAndPtrsMem));
+ }
+
+ unsigned getNumStubs() const { return NumStubs; }
+
+ void *getStub(unsigned Idx) const {
+ return static_cast<char *>(StubsMem.base()) + Idx * ORCABI::StubSize;
+ }
+
+ void **getPtr(unsigned Idx) const {
+ char *PtrsBase =
+ static_cast<char *>(StubsMem.base()) + NumStubs * ORCABI::StubSize;
+ return reinterpret_cast<void **>(PtrsBase) + Idx;
+ }
+
+private:
+ unsigned NumStubs = 0;
+ sys::OwningMemoryBlock StubsMem;
+};
+
/// IndirectStubsManager implementation for the host architecture, e.g.
/// OrcX86_64. (See OrcArchitectureSupport.h).
template <typename TargetT>
@@ -364,13 +434,13 @@
unsigned NewStubsRequired = NumStubs - FreeStubs.size();
unsigned NewBlockId = IndirectStubsInfos.size();
- typename TargetT::IndirectStubsInfo ISI;
- if (auto Err =
- TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired, nullptr))
- return Err;
- for (unsigned I = 0; I < ISI.getNumStubs(); ++I)
+ auto ISI =
+ LocalIndirectStubsInfo<TargetT>::create(NewStubsRequired, PageSize);
+ if (!ISI)
+ return ISI.takeError();
+ for (unsigned I = 0; I < ISI->getNumStubs(); ++I)
FreeStubs.push_back(std::make_pair(NewBlockId, I));
- IndirectStubsInfos.push_back(std::move(ISI));
+ IndirectStubsInfos.push_back(std::move(*ISI));
return Error::success();
}
@@ -379,12 +449,13 @@
auto Key = FreeStubs.back();
FreeStubs.pop_back();
*IndirectStubsInfos[Key.first].getPtr(Key.second) =
- reinterpret_cast<void *>(static_cast<uintptr_t>(InitAddr));
+ jitTargetAddressToPointer<void *>(InitAddr);
StubIndexes[StubName] = std::make_pair(Key, StubFlags);
}
+ unsigned PageSize = sys::Process::getPageSizeEstimate();
std::mutex StubsMutex;
- std::vector<typename TargetT::IndirectStubsInfo> IndirectStubsInfos;
+ std::vector<LocalIndirectStubsInfo<TargetT>> IndirectStubsInfos;
using StubKey = std::pair<uint16_t, uint16_t>;
std::vector<StubKey> FreeStubs;
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
index bcbd72e..c4109a8 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
@@ -25,6 +25,9 @@
#include <vector>
namespace llvm {
+
+class raw_ostream;
+
namespace orc {
/// A utility class for building TargetMachines for JITs.
@@ -79,18 +82,30 @@
return *this;
}
+ /// Get the relocation model.
+ const Optional<Reloc::Model> &getRelocationModel() const { return RM; }
+
/// Set the code model.
JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) {
this->CM = std::move(CM);
return *this;
}
+ /// Get the code model.
+ const Optional<CodeModel::Model> &getCodeModel() const { return CM; }
+
/// Set the LLVM CodeGen optimization level.
JITTargetMachineBuilder &setCodeGenOptLevel(CodeGenOpt::Level OptLevel) {
this->OptLevel = OptLevel;
return *this;
}
+ /// Set subtarget features.
+ JITTargetMachineBuilder &setFeatures(StringRef FeatureString) {
+ Features = SubtargetFeatures(FeatureString);
+ return *this;
+ }
+
/// Add subtarget features.
JITTargetMachineBuilder &
addFeatures(const std::vector<std::string> &FeatureVec);
@@ -101,6 +116,17 @@
/// Access subtarget features.
const SubtargetFeatures &getFeatures() const { return Features; }
+ /// Set TargetOptions.
+ ///
+ /// Note: This operation will overwrite any previously configured options,
+ /// including EmulatedTLS and ExplicitEmulatedTLS which
+ /// the JITTargetMachineBuilder sets by default. Clients are responsible
+ /// for re-enabling these overwritten options.
+ JITTargetMachineBuilder &setOptions(TargetOptions Options) {
+ this->Options = std::move(Options);
+ return *this;
+ }
+
/// Access TargetOptions.
TargetOptions &getOptions() { return Options; }
@@ -113,6 +139,12 @@
/// Access Triple.
const Triple &getTargetTriple() const { return TT; }
+#ifndef NDEBUG
+ /// Debug-dump a JITTargetMachineBuilder.
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const JITTargetMachineBuilder &JTMB);
+#endif
+
private:
Triple TT;
std::string CPU;
@@ -120,7 +152,7 @@
TargetOptions Options;
Optional<Reloc::Model> RM;
Optional<CodeModel::Model> CM;
- CodeGenOpt::Level OptLevel = CodeGenOpt::None;
+ CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
};
} // end namespace orc
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
index b54c7d8..ff0aa02 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -19,8 +19,8 @@
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
-#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ThreadPool.h"
namespace llvm {
@@ -28,6 +28,8 @@
class LLJITBuilderState;
class LLLazyJITBuilderState;
+class ObjectTransformLayer;
+class TargetProcessControl;
/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
///
@@ -35,8 +37,22 @@
class LLJIT {
template <typename, typename, typename> friend class LLJITBuilderSetters;
+ friend void setUpGenericLLVMIRPlatform(LLJIT &J);
+
public:
- static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S);
+ /// Initializer support for LLJIT.
+ class PlatformSupport {
+ public:
+ virtual ~PlatformSupport();
+
+ virtual Error initialize(JITDylib &JD) = 0;
+
+ virtual Error deinitialize(JITDylib &JD) = 0;
+
+ protected:
+ static void setInitTransform(LLJIT &J,
+ IRTransformLayer::TransformFunction T);
+ };
/// Destruct this instance. If a multi-threaded instance, waits for all
/// compile threads to complete.
@@ -45,11 +61,14 @@
/// Returns the ExecutionSession for this instance.
ExecutionSession &getExecutionSession() { return *ES; }
+ /// Returns a reference to the triple for this instance.
+ const Triple &getTargetTriple() const { return TT; }
+
/// Returns a reference to the DataLayout for this instance.
const DataLayout &getDataLayout() const { return DL; }
/// Returns a reference to the JITDylib representing the JIT'd main program.
- JITDylib &getMainJITDylib() { return Main; }
+ JITDylib &getMainJITDylib() { return *Main; }
/// Returns the JITDylib with the given name, or nullptr if no JITDylib with
/// that name exists.
@@ -63,39 +82,49 @@
/// input or elsewhere in the environment then the client should check
/// (e.g. by calling getJITDylibByName) that the given name is not already in
/// use.
- JITDylib &createJITDylib(std::string Name) {
+ Expected<JITDylib &> createJITDylib(std::string Name) {
return ES->createJITDylib(std::move(Name));
}
- /// Convenience method for defining an absolute symbol.
- Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
+ /// Adds an IR module with the given ResourceTracker.
+ Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM);
/// Adds an IR module to the given JITDylib.
Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
/// Adds an IR module to the Main JITDylib.
Error addIRModule(ThreadSafeModule TSM) {
- return addIRModule(Main, std::move(TSM));
+ return addIRModule(*Main, std::move(TSM));
}
/// Adds an object file to the given JITDylib.
+ Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj);
+
+ /// Adds an object file to the given JITDylib.
Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
/// Adds an object file to the given JITDylib.
Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
- return addObjectFile(Main, std::move(Obj));
+ return addObjectFile(*Main, std::move(Obj));
}
/// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
/// look up symbols based on their IR name use the lookup function instead).
Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
- StringRef Name);
+ SymbolStringPtr Name);
+
+ /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
+ /// look up symbols based on their IR name use the lookup function instead).
+ Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
+ StringRef Name) {
+ return lookupLinkerMangled(JD, ES->intern(Name));
+ }
/// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
/// (to look up symbols based on their IR name use the lookup function
/// instead).
Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
- return lookupLinkerMangled(Main, Name);
+ return lookupLinkerMangled(*Main, Name);
}
/// Look up a symbol in JITDylib JD based on its IR symbol name.
@@ -105,41 +134,85 @@
/// Look up a symbol in the main JITDylib based on its IR symbol name.
Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
- return lookup(Main, UnmangledName);
+ return lookup(*Main, UnmangledName);
}
- /// Runs all not-yet-run static constructors.
- Error runConstructors() { return CtorRunner.run(); }
+ /// Set the PlatformSupport instance.
+ void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) {
+ this->PS = std::move(PS);
+ }
- /// Runs all not-yet-run static destructors.
- Error runDestructors() { return DtorRunner.run(); }
+ /// Get the PlatformSupport instance.
+ PlatformSupport *getPlatformSupport() { return PS.get(); }
+
+ /// Run the initializers for the given JITDylib.
+ Error initialize(JITDylib &JD) {
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "LLJIT running initializers for JITDylib \"" << JD.getName()
+ << "\"\n";
+ });
+ assert(PS && "PlatformSupport must be set to run initializers.");
+ return PS->initialize(JD);
+ }
+
+ /// Run the deinitializers for the given JITDylib.
+ Error deinitialize(JITDylib &JD) {
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "LLJIT running deinitializers for JITDylib \"" << JD.getName()
+ << "\"\n";
+ });
+ assert(PS && "PlatformSupport must be set to run initializers.");
+ return PS->deinitialize(JD);
+ }
/// Returns a reference to the ObjLinkingLayer
ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
+ /// Returns a reference to the object transform layer.
+ ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; }
+
+ /// Returns a reference to the IR transform layer.
+ IRTransformLayer &getIRTransformLayer() { return *TransformLayer; }
+
+ /// Returns a reference to the IR compile layer.
+ IRCompileLayer &getIRCompileLayer() { return *CompileLayer; }
+
+ /// Returns a linker-mangled version of UnmangledName.
+ std::string mangle(StringRef UnmangledName) const;
+
+ /// Returns an interned, linker-mangled version of UnmangledName.
+ SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const {
+ return ES->intern(mangle(UnmangledName));
+ }
+
protected:
- static std::unique_ptr<ObjectLayer>
+ static Expected<std::unique_ptr<ObjectLayer>>
createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
+ static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
+ createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB);
+
/// Create an LLJIT instance with a single compile thread.
LLJIT(LLJITBuilderState &S, Error &Err);
- std::string mangle(StringRef UnmangledName);
-
Error applyDataLayout(Module &M);
void recordCtorDtors(Module &M);
std::unique_ptr<ExecutionSession> ES;
- JITDylib &Main;
+ std::unique_ptr<PlatformSupport> PS;
+
+ JITDylib *Main = nullptr;
DataLayout DL;
+ Triple TT;
std::unique_ptr<ThreadPool> CompileThreads;
std::unique_ptr<ObjectLayer> ObjLinkingLayer;
+ std::unique_ptr<ObjectTransformLayer> ObjTransformLayer;
std::unique_ptr<IRCompileLayer> CompileLayer;
-
- CtorDtorRunner CtorRunner, DtorRunner;
+ std::unique_ptr<IRTransformLayer> TransformLayer;
+ std::unique_ptr<IRTransformLayer> InitHelperTransformLayer;
};
/// An extended version of LLJIT that supports lazy function-at-a-time
@@ -149,24 +222,21 @@
public:
- /// Set an IR transform (e.g. pass manager pipeline) to run on each function
- /// when it is compiled.
- void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) {
- TransformLayer->setTransform(std::move(Transform));
- }
-
/// Sets the partition function.
void
setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
CODLayer->setPartitionFunction(std::move(Partition));
}
+ /// Returns a reference to the on-demand layer.
+ CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; }
+
/// Add a module to be lazily compiled to JITDylib JD.
Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
/// Add a module to be lazily compiled to the main JITDylib.
Error addLazyIRModule(ThreadSafeModule M) {
- return addLazyIRModule(Main, std::move(M));
+ return addLazyIRModule(*Main, std::move(M));
}
private:
@@ -175,19 +245,29 @@
LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
std::unique_ptr<LazyCallThroughManager> LCTMgr;
- std::unique_ptr<IRTransformLayer> TransformLayer;
std::unique_ptr<CompileOnDemandLayer> CODLayer;
};
class LLJITBuilderState {
public:
- using CreateObjectLinkingLayerFunction =
- std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>;
+ using ObjectLinkingLayerCreator =
+ std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &,
+ const Triple &)>;
+
+ using CompileFunctionCreator =
+ std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(
+ JITTargetMachineBuilder JTMB)>;
+
+ using PlatformSetupFunction = std::function<Error(LLJIT &J)>;
std::unique_ptr<ExecutionSession> ES;
Optional<JITTargetMachineBuilder> JTMB;
- CreateObjectLinkingLayerFunction CreateObjectLinkingLayer;
+ Optional<DataLayout> DL;
+ ObjectLinkingLayerCreator CreateObjectLinkingLayer;
+ CompileFunctionCreator CreateCompileFunction;
+ PlatformSetupFunction SetUpPlatform;
unsigned NumCompileThreads = 0;
+ TargetProcessControl *TPC = nullptr;
/// Called prior to JIT class construcion to fix up defaults.
Error prepareForConstruction();
@@ -196,6 +276,13 @@
template <typename JITType, typename SetterImpl, typename State>
class LLJITBuilderSetters {
public:
+
+ /// Set an ExecutionSession for this instance.
+ SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) {
+ impl().ES = std::move(ES);
+ return impl();
+ }
+
/// Set the JITTargetMachineBuilder for this instance.
///
/// If this method is not called, JITTargetMachineBuilder::detectHost will be
@@ -211,17 +298,45 @@
return impl().JTMB;
}
+ /// Set a DataLayout for this instance. If no data layout is specified then
+ /// the target's default data layout will be used.
+ SetterImpl &setDataLayout(Optional<DataLayout> DL) {
+ impl().DL = std::move(DL);
+ return impl();
+ }
+
/// Set an ObjectLinkingLayer creation function.
///
/// If this method is not called, a default creation function will be used
/// that will construct an RTDyldObjectLinkingLayer.
- SetterImpl &setCreateObjectLinkingLayer(
- LLJITBuilderState::CreateObjectLinkingLayerFunction
- CreateObjectLinkingLayer) {
+ SetterImpl &setObjectLinkingLayerCreator(
+ LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) {
impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer);
return impl();
}
+ /// Set a CompileFunctionCreator.
+ ///
+ /// If this method is not called, a default creation function wil be used
+ /// that will construct a basic IR compile function that is compatible with
+ /// the selected number of threads (SimpleCompiler for '0' compile threads,
+ /// ConcurrentIRCompiler otherwise).
+ SetterImpl &setCompileFunctionCreator(
+ LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) {
+ impl().CreateCompileFunction = std::move(CreateCompileFunction);
+ return impl();
+ }
+
+ /// Set up an PlatformSetupFunction.
+ ///
+ /// If this method is not called then setUpGenericLLVMIRPlatform
+ /// will be used to configure the JIT's platform support.
+ SetterImpl &
+ setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) {
+ impl().SetUpPlatform = std::move(SetUpPlatform);
+ return impl();
+ }
+
/// Set the number of compile threads to use.
///
/// If set to zero, compilation will be performed on the execution thread when
@@ -235,6 +350,17 @@
return impl();
}
+ /// Set a TargetProcessControl object.
+ ///
+ /// If the platform uses ObjectLinkingLayer by default and no
+ /// ObjectLinkingLayerCreator has been set then the TargetProcessControl
+ /// object will be used to supply the memory manager for the
+ /// ObjectLinkingLayer.
+ SetterImpl &setTargetProcessControl(TargetProcessControl &TPC) {
+ impl().TPC = &TPC;
+ return impl();
+ }
+
/// Create an instance of the JIT.
Expected<std::unique_ptr<JITType>> create() {
if (auto Err = impl().prepareForConstruction())
@@ -310,6 +436,26 @@
public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
LLLazyJITBuilderState> {};
+/// Configure the LLJIT instance to scrape modules for llvm.global_ctors and
+/// llvm.global_dtors variables and (if present) build initialization and
+/// deinitialization functions. Platform specific initialization configurations
+/// should be preferred where available.
+void setUpGenericLLVMIRPlatform(LLJIT &J);
+
+/// Configure the LLJIT instance to use MachOPlatform support.
+///
+/// Warning: MachOPlatform *requires* that LLJIT be configured to use
+/// ObjectLinkingLayer (default on platforms supported by JITLink). If
+/// MachOPlatform is used with RTDyldObjectLinkingLayer it will result in
+/// undefined behavior).
+///
+/// MachOPlatform installs an ObjectLinkingLayer plugin to scrape initializers
+/// from the __mod_inits section. It also provides interposes for the dlfcn
+/// functions (dlopen, dlclose, dlsym, dlerror) that work for JITDylibs as
+/// well as regular libraries (JITDylibs will be preferenced, so make sure
+/// your JITDylib names do not shadow any real library paths).
+Error setUpMachOPlatform(LLJIT &J);
+
} // End namespace orc
} // End namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
deleted file mode 100644
index 92efded..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
+++ /dev/null
@@ -1,58 +0,0 @@
-//===- LambdaResolverMM - Redirect symbol lookup via a functor --*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied
-// functor for symbol resolution.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
-#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include <memory>
-
-namespace llvm {
-namespace orc {
-
-template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
-class LambdaResolver : public LegacyJITSymbolResolver {
-public:
- LambdaResolver(DylibLookupFtorT DylibLookupFtor,
- ExternalLookupFtorT ExternalLookupFtor)
- : DylibLookupFtor(DylibLookupFtor),
- ExternalLookupFtor(ExternalLookupFtor) {}
-
- JITSymbol findSymbolInLogicalDylib(const std::string &Name) final {
- return DylibLookupFtor(Name);
- }
-
- JITSymbol findSymbol(const std::string &Name) final {
- return ExternalLookupFtor(Name);
- }
-
-private:
- DylibLookupFtorT DylibLookupFtor;
- ExternalLookupFtorT ExternalLookupFtor;
-};
-
-template <typename DylibLookupFtorT,
- typename ExternalLookupFtorT>
-std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>>
-createLambdaResolver(DylibLookupFtorT DylibLookupFtor,
- ExternalLookupFtorT ExternalLookupFtor) {
- using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>;
- return make_unique<LR>(std::move(DylibLookupFtor),
- std::move(ExternalLookupFtor));
-}
-
-} // end namespace orc
-} // end namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
index 8f9bd70..f9cc155 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -14,6 +14,7 @@
#define LLVM_EXECUTIONENGINE_ORC_LAYER_H
#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -21,15 +22,62 @@
namespace llvm {
namespace orc {
+/// 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,
+ const IRSymbolMapper::ManglingOptions &MO,
+ ThreadSafeModule TSM);
+
+ /// Create an IRMaterializationLayer from a module, and pre-existing
+ /// SymbolFlags and SymbolToDefinition maps. The maps must provide
+ /// entries for each definition in M.
+ /// This constructor is useful for delegating work from one
+ /// IRMaterializationUnit to another.
+ IRMaterializationUnit(ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
+ SymbolStringPtr InitSymbol,
+ SymbolNameToDefinitionMap SymbolToDefinition);
+
+ /// Return the ModuleIdentifier as the name for this MaterializationUnit.
+ StringRef getName() const override;
+
+ /// Return a reference to the contained ThreadSafeModule.
+ const ThreadSafeModule &getModule() const { return TSM; }
+
+protected:
+ ThreadSafeModule TSM;
+ SymbolNameToDefinitionMap SymbolToDefinition;
+
+private:
+ static SymbolStringPtr getInitSymbol(ExecutionSession &ES,
+ const ThreadSafeModule &TSM);
+
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
+};
+
/// Interface for layers that accept LLVM IR.
class IRLayer {
public:
- IRLayer(ExecutionSession &ES);
+ IRLayer(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions *&MO)
+ : ES(ES), MO(MO) {}
+
virtual ~IRLayer();
/// Returns the ExecutionSession for this layer.
ExecutionSession &getExecutionSession() { return ES; }
+ /// Get the mangling options for this layer.
+ const IRSymbolMapper::ManglingOptions *&getManglingOptions() const {
+ return MO;
+ }
+
/// Sets the CloneToNewContextOnEmit flag (false by default).
///
/// When set, IR modules added to this layer will be cloned on to a new
@@ -46,67 +94,38 @@
/// Returns the current value of the CloneToNewContextOnEmit flag.
bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
+ /// Add a MaterializatinoUnit representing the given IR to the JITDylib
+ /// targeted by the given tracker.
+ virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM);
+
/// Adds a MaterializationUnit representing the given IR to the given
- /// JITDylib.
- virtual Error add(JITDylib &JD, ThreadSafeModule TSM,
- VModuleKey K = VModuleKey());
+ /// JITDylib. If RT is not specif
+ Error add(JITDylib &JD, ThreadSafeModule TSM) {
+ return add(JD.getDefaultResourceTracker(), std::move(TSM));
+ }
/// Emit should materialize the given IR.
- virtual void emit(MaterializationResponsibility R, ThreadSafeModule TSM) = 0;
+ virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
+ ThreadSafeModule TSM) = 0;
private:
bool CloneToNewContextOnEmit = false;
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, ThreadSafeModule TSM,
- VModuleKey K);
-
- /// 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(ThreadSafeModule TSM, VModuleKey K,
- SymbolFlagsMap SymbolFlags,
- SymbolNameToDefinitionMap SymbolToDefinition);
-
- /// Return the ModuleIdentifier as the name for this MaterializationUnit.
- StringRef getName() const override;
-
- const ThreadSafeModule &getModule() const { return TSM; }
-
-protected:
- ThreadSafeModule TSM;
- SymbolNameToDefinitionMap SymbolToDefinition;
-
-private:
- void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
+ const IRSymbolMapper::ManglingOptions *&MO;
};
/// MaterializationUnit that materializes modules by calling the 'emit' method
/// on the given IRLayer.
class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
public:
- BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K,
+ BasicIRLayerMaterializationUnit(IRLayer &L,
+ const IRSymbolMapper::ManglingOptions &MO,
ThreadSafeModule TSM);
private:
-
- void materialize(MaterializationResponsibility R) override;
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
IRLayer &L;
- VModuleKey K;
};
/// Interface for Layers that accept object files.
@@ -120,11 +139,14 @@
/// Adds a MaterializationUnit representing the given IR to the given
/// JITDylib.
- virtual Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
- VModuleKey K = VModuleKey());
+ virtual Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O);
+
+ Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
+ return add(JD.getDefaultResourceTracker(), std::move(O));
+ }
/// Emit should materialize the given IR.
- virtual void emit(MaterializationResponsibility R,
+ virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) = 0;
private:
@@ -136,30 +158,24 @@
class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
public:
static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
- Create(ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+ Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> O);
- BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,
+ BasicObjectLayerMaterializationUnit(ObjectLayer &L,
std::unique_ptr<MemoryBuffer> O,
- SymbolFlagsMap SymbolFlags);
+ SymbolFlagsMap SymbolFlags,
+ SymbolStringPtr InitSymbol);
/// Return the buffer's identifier as the name for this MaterializationUnit.
StringRef getName() const override;
private:
-
- void materialize(MaterializationResponsibility R) override;
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
ObjectLayer &L;
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
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
deleted file mode 100644
index e5c5feb..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ /dev/null
@@ -1,260 +0,0 @@
-//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Contains the definition for a lazy-emitting layer for the JIT.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
-#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/IR/GlobalValue.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <list>
-#include <memory>
-#include <string>
-
-namespace llvm {
-namespace orc {
-
-/// Lazy-emitting IR layer.
-///
-/// This layer accepts LLVM IR Modules (via addModule) but does not
-/// immediately emit them the layer below. Instead, emission to the base layer
-/// is deferred until the first time the client requests the address (via
-/// JITSymbol::getAddress) for a symbol contained in this layer.
-template <typename BaseLayerT> class LazyEmittingLayer {
-private:
- class EmissionDeferredModule {
- public:
- EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M)
- : K(std::move(K)), M(std::move(M)) {}
-
- JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
- switch (EmitState) {
- case NotEmitted:
- if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
- // Create a std::string version of Name to capture here - the argument
- // (a StringRef) may go away before the lambda is executed.
- // FIXME: Use capture-init when we move to C++14.
- std::string PName = Name;
- JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
- auto GetAddress =
- [this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> {
- if (this->EmitState == Emitting)
- return 0;
- else if (this->EmitState == NotEmitted) {
- this->EmitState = Emitting;
- if (auto Err = this->emitToBaseLayer(B))
- return std::move(Err);
- this->EmitState = Emitted;
- }
- if (auto Sym = B.findSymbolIn(K, PName, ExportedSymbolsOnly))
- return Sym.getAddress();
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- else
- llvm_unreachable("Successful symbol lookup should return "
- "definition address here");
- };
- return JITSymbol(std::move(GetAddress), Flags);
- } else
- return nullptr;
- case Emitting:
- // Calling "emit" can trigger a recursive call to 'find' (e.g. to check
- // for pre-existing definitions of common-symbol), but any symbol in
- // this module would already have been found internally (in the
- // RuntimeDyld that did the lookup), so just return a nullptr here.
- return nullptr;
- case Emitted:
- return B.findSymbolIn(K, Name, ExportedSymbolsOnly);
- }
- llvm_unreachable("Invalid emit-state.");
- }
-
- Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
- return EmitState != NotEmitted ? BaseLayer.removeModule(K)
- : Error::success();
- }
-
- void emitAndFinalize(BaseLayerT &BaseLayer) {
- assert(EmitState != Emitting &&
- "Cannot emitAndFinalize while already emitting");
- if (EmitState == NotEmitted) {
- EmitState = Emitting;
- emitToBaseLayer(BaseLayer);
- EmitState = Emitted;
- }
- BaseLayer.emitAndFinalize(K);
- }
-
- private:
-
- const GlobalValue* searchGVs(StringRef Name,
- bool ExportedSymbolsOnly) const {
- // FIXME: We could clean all this up if we had a way to reliably demangle
- // names: We could just demangle name and search, rather than
- // mangling everything else.
-
- // If we have already built the mangled name set then just search it.
- if (MangledSymbols) {
- auto VI = MangledSymbols->find(Name);
- if (VI == MangledSymbols->end())
- return nullptr;
- auto GV = VI->second;
- if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
- return GV;
- return nullptr;
- }
-
- // If we haven't built the mangled name set yet, try to build it. As an
- // optimization this will leave MangledNames set to nullptr if we find
- // Name in the process of building the set.
- return buildMangledSymbols(Name, ExportedSymbolsOnly);
- }
-
- Error emitToBaseLayer(BaseLayerT &BaseLayer) {
- // We don't need the mangled names set any more: Once we've emitted this
- // to the base layer we'll just look for symbols there.
- MangledSymbols.reset();
- return BaseLayer.addModule(std::move(K), std::move(M));
- }
-
- // If the mangled name of the given GlobalValue matches the given search
- // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
- // return the symbol. Otherwise, add the mangled name to the Names map and
- // return nullptr.
- const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
- const GlobalValue &GV,
- const Mangler &Mang, StringRef SearchName,
- bool ExportedSymbolsOnly) const {
- // Modules don't "provide" decls or common symbols.
- if (GV.isDeclaration() || GV.hasCommonLinkage())
- return nullptr;
-
- // Mangle the GV name.
- std::string MangledName;
- {
- raw_string_ostream MangledNameStream(MangledName);
- Mang.getNameWithPrefix(MangledNameStream, &GV, false);
- }
-
- // Check whether this is the name we were searching for, and if it is then
- // bail out early.
- if (MangledName == SearchName)
- if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
- return &GV;
-
- // Otherwise add this to the map for later.
- Names[MangledName] = &GV;
- return nullptr;
- }
-
- // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
- // to nullptr) if the given SearchName is found while building the map.
- const GlobalValue* buildMangledSymbols(StringRef SearchName,
- bool ExportedSymbolsOnly) const {
- assert(!MangledSymbols && "Mangled symbols map already exists?");
-
- auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
-
- Mangler Mang;
-
- for (const auto &GO : M->global_objects())
- if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
- ExportedSymbolsOnly))
- return GV;
-
- MangledSymbols = std::move(Symbols);
- return nullptr;
- }
-
- enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
- VModuleKey K;
- std::unique_ptr<Module> M;
- mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
- };
-
- BaseLayerT &BaseLayer;
- std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap;
-
-public:
-
- /// Construct a lazy emitting layer.
- LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
-
- /// 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] =
- llvm::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
- return Error::success();
- }
-
- /// 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.
- Error removeModule(VModuleKey K) {
- auto I = ModuleMap.find(K);
- assert(I != ModuleMap.end() && "VModuleKey K not valid here");
- auto EDM = std::move(I.second);
- ModuleMap.erase(I);
- return EDM->removeModuleFromBaseLayer(BaseLayer);
- }
-
- /// 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.
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- // Look for the symbol among existing definitions.
- if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
- return Symbol;
-
- // If not found then search the deferred modules. If any of these contain a
- // definition of 'Name' then they will return a JITSymbol that will emit
- // the corresponding module when the symbol address is requested.
- for (auto &KV : ModuleMap)
- if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer))
- return Symbol;
-
- // If no definition found anywhere return a null symbol.
- return nullptr;
- }
-
- /// 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) {
- assert(ModuleMap.count(K) && "VModuleKey K not valid here");
- return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
- }
-
- /// Immediately emit and finalize the module represented by the given
- /// key.
- Error emitAndFinalize(VModuleKey K) {
- assert(ModuleMap.count(K) && "VModuleKey K not valid here");
- return ModuleMap[K]->emitAndFinalize(BaseLayer);
- }
-};
-
-} // end namespace orc
-} // end namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h
index 9fdd1d1..e6a9d89 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyReexports.h
@@ -16,8 +16,10 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
#define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
+#include "llvm/ExecutionEngine/Orc/Speculation.h"
namespace llvm {
@@ -35,73 +37,48 @@
/// function.
class LazyCallThroughManager {
public:
- /// Clients will want to take some action on first resolution, e.g. updating
- /// a stub pointer. Instances of this class can be used to implement this.
- class NotifyResolvedFunction {
- public:
- virtual ~NotifyResolvedFunction() {}
+ using NotifyResolvedFunction =
+ unique_function<Error(JITTargetAddress ResolvedAddr)>;
- /// Called the first time a lazy call through is executed and the target
- /// symbol resolved.
- virtual Error operator()(JITDylib &SourceJD,
- const SymbolStringPtr &SymbolName,
- JITTargetAddress ResolvedAddr) = 0;
-
- private:
- virtual void anchor();
- };
-
- template <typename NotifyResolvedImpl>
- class NotifyResolvedFunctionImpl : public NotifyResolvedFunction {
- public:
- NotifyResolvedFunctionImpl(NotifyResolvedImpl NotifyResolved)
- : NotifyResolved(std::move(NotifyResolved)) {}
- Error operator()(JITDylib &SourceJD, const SymbolStringPtr &SymbolName,
- JITTargetAddress ResolvedAddr) {
- return NotifyResolved(SourceJD, SymbolName, ResolvedAddr);
- }
-
- private:
- NotifyResolvedImpl NotifyResolved;
- };
-
- /// Create a shared NotifyResolvedFunction from a given type that is
- /// callable with the correct signature.
- template <typename NotifyResolvedImpl>
- static std::unique_ptr<NotifyResolvedFunction>
- createNotifyResolvedFunction(NotifyResolvedImpl NotifyResolved) {
- return llvm::make_unique<NotifyResolvedFunctionImpl<NotifyResolvedImpl>>(
- std::move(NotifyResolved));
- }
+ LazyCallThroughManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP);
// Return a free call-through trampoline and bind it to look up and call
// through to the given symbol.
- Expected<JITTargetAddress> getCallThroughTrampoline(
- JITDylib &SourceJD, SymbolStringPtr SymbolName,
- std::shared_ptr<NotifyResolvedFunction> NotifyResolved);
+ Expected<JITTargetAddress>
+ getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName,
+ NotifyResolvedFunction NotifyResolved);
+
+ void resolveTrampolineLandingAddress(
+ JITTargetAddress TrampolineAddr,
+ TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved);
+
+ virtual ~LazyCallThroughManager() = default;
protected:
- LazyCallThroughManager(ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddr,
- std::unique_ptr<TrampolinePool> TP);
+ using NotifyLandingResolvedFunction =
+ TrampolinePool::NotifyLandingResolvedFunction;
- JITTargetAddress callThroughToSymbol(JITTargetAddress TrampolineAddr);
+ struct ReexportsEntry {
+ JITDylib *SourceJD;
+ SymbolStringPtr SymbolName;
+ };
- void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
- this->TP = std::move(TP);
- }
+ JITTargetAddress reportCallThroughError(Error Err);
+ Expected<ReexportsEntry> findReexport(JITTargetAddress TrampolineAddr);
+ Error notifyResolved(JITTargetAddress TrampolineAddr,
+ JITTargetAddress ResolvedAddr);
+ void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
private:
- using ReexportsMap =
- std::map<JITTargetAddress, std::pair<JITDylib *, SymbolStringPtr>>;
+ using ReexportsMap = std::map<JITTargetAddress, ReexportsEntry>;
- using NotifiersMap =
- std::map<JITTargetAddress, std::shared_ptr<NotifyResolvedFunction>>;
+ using NotifiersMap = std::map<JITTargetAddress, NotifyResolvedFunction>;
std::mutex LCTMMutex;
ExecutionSession &ES;
JITTargetAddress ErrorHandlerAddr;
- std::unique_ptr<TrampolinePool> TP;
+ TrampolinePool *TP = nullptr;
ReexportsMap Reexports;
NotifiersMap Notifiers;
};
@@ -109,23 +86,31 @@
/// A lazy call-through manager that builds trampolines in the current process.
class LocalLazyCallThroughManager : public LazyCallThroughManager {
private:
+ using NotifyTargetResolved = unique_function<void(JITTargetAddress)>;
+
LocalLazyCallThroughManager(ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddr)
: LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
template <typename ORCABI> Error init() {
auto TP = LocalTrampolinePool<ORCABI>::Create(
- [this](JITTargetAddress TrampolineAddr) {
- return callThroughToSymbol(TrampolineAddr);
+ [this](JITTargetAddress TrampolineAddr,
+ TrampolinePool::NotifyLandingResolvedFunction
+ NotifyLandingResolved) {
+ resolveTrampolineLandingAddress(TrampolineAddr,
+ std::move(NotifyLandingResolved));
});
if (!TP)
return TP.takeError();
- setTrampolinePool(std::move(*TP));
+ this->TP = std::move(*TP);
+ setTrampolinePool(*this->TP);
return Error::success();
}
+ std::unique_ptr<TrampolinePool> TP;
+
public:
/// Create a LocalLazyCallThroughManager using the given ABI. See
/// createLocalLazyCallThroughManager.
@@ -159,12 +144,12 @@
IndirectStubsManager &ISManager,
JITDylib &SourceJD,
SymbolAliasMap CallableAliases,
- VModuleKey K);
+ ImplSymbolMap *SrcJDLoc);
StringRef getName() const override;
private:
- void materialize(MaterializationResponsibility R) override;
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
@@ -172,8 +157,7 @@
IndirectStubsManager &ISManager;
JITDylib &SourceJD;
SymbolAliasMap CallableAliases;
- std::shared_ptr<LazyCallThroughManager::NotifyResolvedFunction>
- NotifyResolved;
+ ImplSymbolMap *AliaseeTable;
};
/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
@@ -182,10 +166,10 @@
inline std::unique_ptr<LazyReexportsMaterializationUnit>
lazyReexports(LazyCallThroughManager &LCTManager,
IndirectStubsManager &ISManager, JITDylib &SourceJD,
- SymbolAliasMap CallableAliases, VModuleKey K = VModuleKey()) {
- return llvm::make_unique<LazyReexportsMaterializationUnit>(
- LCTManager, ISManager, SourceJD, std::move(CallableAliases),
- std::move(K));
+ SymbolAliasMap CallableAliases,
+ ImplSymbolMap *SrcJDLoc = nullptr) {
+ return std::make_unique<LazyReexportsMaterializationUnit>(
+ LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
}
} // End namespace orc
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
deleted file mode 100644
index f9cbbf6..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
+++ /dev/null
@@ -1,215 +0,0 @@
-//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Contains core ORC APIs.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
-#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
-
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
-
-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 subset of the given symbols that the caller is responsible for
- /// materializing.
- virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
-
- /// For each symbol in Symbols that can be found, assigns that symbols
- /// value in Query. Returns the set of symbols that could not be found.
- 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 GetResponsibilitySetFn, typename LookupFn>
-class LambdaSymbolResolver final : public SymbolResolver {
-public:
- template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
- LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
- LookupFnRef &&Lookup)
- : GetResponsibilitySet(
- std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
- Lookup(std::forward<LookupFnRef>(Lookup)) {}
-
- SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
- return GetResponsibilitySet(Symbols);
- }
-
- SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) final {
- return Lookup(std::move(Query), std::move(Symbols));
- }
-
-private:
- GetResponsibilitySetFn GetResponsibilitySet;
- LookupFn Lookup;
-};
-
-/// Creates a SymbolResolver implementation from the pair of supplied
-/// function objects.
-template <typename GetResponsibilitySetFn, typename LookupFn>
-std::unique_ptr<LambdaSymbolResolver<
- typename std::remove_cv<
- typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
- typename std::remove_cv<
- typename std::remove_reference<LookupFn>::type>::type>>
-createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
- LookupFn &&Lookup) {
- using LambdaSymbolResolverImpl = LambdaSymbolResolver<
- typename std::remove_cv<
- typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
- typename std::remove_cv<
- typename std::remove_reference<LookupFn>::type>::type>;
- return llvm::make_unique<LambdaSymbolResolverImpl>(
- std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
- std::forward<LookupFn>(Lookup));
-}
-
-/// Legacy adapter. Remove once we kill off the old ORC layers.
-class JITSymbolResolverAdapter : public JITSymbolResolver {
-public:
- JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
- MaterializationResponsibility *MR);
- Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
- void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
-
-private:
- ExecutionSession &ES;
- std::set<SymbolStringPtr> ResolvedStrings;
- SymbolResolver &R;
- MaterializationResponsibility *MR;
-};
-
-/// Use the given legacy-style FindSymbol function (i.e. a function that takes
-/// a const std::string& or StringRef and returns a JITSymbol) to get the
-/// subset of symbols that the caller is responsible for materializing. If any
-/// JITSymbol returned by FindSymbol is in an error state the function returns
-/// immediately with that error.
-///
-/// Useful for implementing getResponsibilitySet bodies that query legacy
-/// resolvers.
-template <typename FindSymbolFn>
-Expected<SymbolNameSet>
-getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
- FindSymbolFn FindSymbol) {
- SymbolNameSet Result;
-
- for (auto &S : Symbols) {
- if (JITSymbol Sym = FindSymbol(*S)) {
- if (!Sym.getFlags().isStrong())
- Result.insert(S);
- } else if (auto Err = Sym.takeError())
- return std::move(Err);
- }
-
- return Result;
-}
-
-/// 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.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(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.notifySymbolMetRequiredState(
- S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
- NewSymbolsResolved = true;
- } else {
- ES.legacyFailQuery(Query, Addr.takeError());
- return SymbolNameSet();
- }
- } else if (auto Err = Sym.takeError()) {
- ES.legacyFailQuery(Query, std::move(Err));
- return SymbolNameSet();
- } else
- SymbolsNotFound.insert(S);
- }
-
- if (NewSymbolsResolved && Query.isComplete())
- Query.handleComplete();
-
- return SymbolsNotFound;
-}
-
-/// 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(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
- ErrorReporter ReportError)
- : ES(ES), LegacyLookup(std::move(LegacyLookup)),
- ReportError(std::move(ReportError)) {}
-
- SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
- if (auto ResponsibilitySet =
- getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
- return std::move(*ResponsibilitySet);
- else {
- ReportError(ResponsibilitySet.takeError());
- return SymbolNameSet();
- }
- }
-
- SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) final {
- return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
- }
-
-private:
- ExecutionSession &ES;
- LegacyLookupFn LegacyLookup;
- ErrorReporter ReportError;
-};
-
-template <typename LegacyLookupFn>
-std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
-createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
- std::function<void(Error)> ErrorReporter) {
- return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
- ES, std::move(LegacyLookup), std::move(ErrorReporter));
-}
-
-} // End namespace orc
-} // End namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
new file mode 100644
index 0000000..90e1d47
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
@@ -0,0 +1,173 @@
+//===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for executing JIT'd MachO in Orc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
+#define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+
+#include <future>
+#include <thread>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+/// Enable registration of JIT'd ObjC classes and selectors.
+Error enableObjCRegistration(const char *PathToLibObjC);
+bool objCRegistrationEnabled();
+
+class MachOJITDylibInitializers {
+public:
+ struct SectionExtent {
+ SectionExtent() = default;
+ SectionExtent(JITTargetAddress Address, uint64_t NumPtrs)
+ : Address(Address), NumPtrs(NumPtrs) {}
+ JITTargetAddress Address = 0;
+ uint64_t NumPtrs = 0;
+ };
+
+ using RawPointerSectionList = std::vector<SectionExtent>;
+
+ void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
+ this->ObjCImageInfoAddr = ObjCImageInfoAddr;
+ }
+
+ void addModInitsSection(SectionExtent ModInit) {
+ ModInitSections.push_back(std::move(ModInit));
+ }
+
+ const RawPointerSectionList &getModInitsSections() const {
+ return ModInitSections;
+ }
+
+ void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
+ ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
+ }
+
+ const RawPointerSectionList &getObjCSelRefsSections() const {
+ return ObjCSelRefsSections;
+ }
+
+ void addObjCClassListSection(SectionExtent ObjCClassList) {
+ ObjCClassListSections.push_back(std::move(ObjCClassList));
+ }
+
+ const RawPointerSectionList &getObjCClassListSections() const {
+ return ObjCClassListSections;
+ }
+
+ void runModInits() const;
+ void registerObjCSelectors() const;
+ Error registerObjCClasses() const;
+
+private:
+
+ JITTargetAddress ObjCImageInfoAddr;
+ RawPointerSectionList ModInitSections;
+ RawPointerSectionList ObjCSelRefsSections;
+ RawPointerSectionList ObjCClassListSections;
+};
+
+class MachOJITDylibDeinitializers {};
+
+/// Mediates between MachO initialization and ExecutionSession state.
+class MachOPlatform : public Platform {
+public:
+ using InitializerSequence =
+ std::vector<std::pair<JITDylib *, MachOJITDylibInitializers>>;
+
+ using DeinitializerSequence =
+ std::vector<std::pair<JITDylib *, MachOJITDylibDeinitializers>>;
+
+ MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+ std::unique_ptr<MemoryBuffer> StandardSymbolsObject);
+
+ ExecutionSession &getExecutionSession() const { return ES; }
+
+ Error setupJITDylib(JITDylib &JD) override;
+ Error notifyAdding(ResourceTracker &RT,
+ const MaterializationUnit &MU) override;
+ Error notifyRemoving(ResourceTracker &RT) override;
+
+ Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);
+
+ Expected<DeinitializerSequence> getDeinitializerSequence(JITDylib &JD);
+
+private:
+ // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func,
+ // __objc_classlist and __sel_ref sections and records their extents so that
+ // they can be run in the target process.
+ class InitScraperPlugin : public ObjectLinkingLayer::Plugin {
+ public:
+ InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}
+
+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+ jitlink::PassConfiguration &Config) override;
+
+ LocalDependenciesMap getSyntheticSymbolLocalDependencies(
+ MaterializationResponsibility &MR) override;
+
+ // FIXME: We should be tentatively tracking scraped sections and discarding
+ // if the MR fails.
+ Error notifyFailed(MaterializationResponsibility &MR) override {
+ return Error::success();
+ }
+
+ Error notifyRemovingResources(ResourceKey K) override {
+ return Error::success();
+ }
+
+ void notifyTransferringResources(ResourceKey DstKey,
+ ResourceKey SrcKey) override {}
+
+ private:
+ using InitSymbolDepMap =
+ DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;
+
+ void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,
+ jitlink::LinkGraph &G,
+ StringRef SectionName);
+
+ Error processObjCImageInfo(jitlink::LinkGraph &G,
+ MaterializationResponsibility &MR);
+
+ std::mutex InitScraperMutex;
+ MachOPlatform &MP;
+ DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
+ InitSymbolDepMap InitSymbolDeps;
+ };
+
+ void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
+ MachOJITDylibInitializers::SectionExtent ModInits,
+ MachOJITDylibInitializers::SectionExtent ObjCSelRefs,
+ MachOJITDylibInitializers::SectionExtent ObjCClassList);
+
+ ExecutionSession &ES;
+ ObjectLinkingLayer &ObjLinkingLayer;
+ std::unique_ptr<MemoryBuffer> StandardSymbolsObject;
+
+ DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
+
+ // InitSeqs gets its own mutex to avoid locking the whole session when
+ // aggregating data from the jitlink.
+ std::mutex InitSeqsMutex;
+ DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Mangling.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Mangling.h
new file mode 100644
index 0000000..e0f770a
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Mangling.h
@@ -0,0 +1,66 @@
+//===------ Mangling.h -- Name Mangling Utilities for ORC -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Name mangling utilities for ORC.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_MANGLING_H
+#define LLVM_EXECUTIONENGINE_ORC_MANGLING_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace llvm {
+namespace orc {
+
+/// Mangles symbol names then uniques them in the context of an
+/// ExecutionSession.
+class MangleAndInterner {
+public:
+ MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
+ SymbolStringPtr operator()(StringRef Name);
+
+private:
+ ExecutionSession &ES;
+ const DataLayout &DL;
+};
+
+/// Maps IR global values to their linker symbol names / flags.
+///
+/// This utility can be used when adding new IR globals in the JIT.
+class IRSymbolMapper {
+public:
+ struct ManglingOptions {
+ bool EmulatedTLS = false;
+ };
+
+ using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
+
+ /// Add mangled symbols for the given GlobalValues to SymbolFlags.
+ /// If a SymbolToDefinitionMap pointer is supplied then it will be populated
+ /// with Name-to-GlobalValue* mappings. Note that this mapping is not
+ /// necessarily one-to-one: thread-local GlobalValues, for example, may
+ /// produce more than one symbol, in which case the map will contain duplicate
+ /// values.
+ static void add(ExecutionSession &ES, const ManglingOptions &MO,
+ ArrayRef<GlobalValue *> GVs, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDefinition = nullptr);
+};
+
+/// 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.
+Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>>
+getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer);
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_MANGLING_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
deleted file mode 100644
index ffa37a1..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===------ NullResolver.h - Reject symbol lookup requests ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines a RuntimeDyld::SymbolResolver subclass that rejects all symbol
-// resolution requests, for clients that have no cross-object fixups.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
-#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
-
-#include "llvm/ExecutionEngine/Orc/Legacy.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
-
-namespace llvm {
-namespace orc {
-
-class NullResolver : public SymbolResolver {
-public:
- SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final;
-
- SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) final;
-};
-
-/// SymbolResolver impliementation that rejects all resolution requests.
-/// Useful for clients that have no cross-object fixups.
-class NullLegacyResolver : public LegacyJITSymbolResolver {
-public:
- JITSymbol findSymbol(const std::string &Name) final;
-
- JITSymbol findSymbolInLogicalDylib(const std::string &Name) final;
-};
-
-} // End namespace orc.
-} // End namespace llvm.
-
-#endif // LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index c1e7d27..f2975e2 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -35,6 +35,8 @@
namespace jitlink {
class EHFrameRegistrar;
+class LinkGraph;
+class Symbol;
} // namespace jitlink
namespace object {
@@ -50,7 +52,7 @@
/// Clients can use this class to add relocatable object files to an
/// ExecutionSession, and it typically serves as the base layer (underneath
/// a compiling layer like IRCompileLayer) for the rest of the JIT.
-class ObjectLinkingLayer : public ObjectLayer {
+class ObjectLinkingLayer : public ObjectLayer, private ResourceManager {
friend class ObjectLinkingLayerJITLinkContext;
public:
@@ -59,28 +61,57 @@
/// configured.
class Plugin {
public:
+ using JITLinkSymbolVector = std::vector<const jitlink::Symbol *>;
+ using LocalDependenciesMap = DenseMap<SymbolStringPtr, JITLinkSymbolVector>;
+
virtual ~Plugin();
virtual void modifyPassConfig(MaterializationResponsibility &MR,
const Triple &TT,
jitlink::PassConfiguration &Config) {}
+
virtual void notifyLoaded(MaterializationResponsibility &MR) {}
virtual Error notifyEmitted(MaterializationResponsibility &MR) {
return Error::success();
}
- virtual Error notifyRemovingModule(VModuleKey K) {
- return Error::success();
+ virtual Error notifyFailed(MaterializationResponsibility &MR) = 0;
+ virtual Error notifyRemovingResources(ResourceKey K) = 0;
+ virtual void notifyTransferringResources(ResourceKey DstKey,
+ ResourceKey SrcKey) = 0;
+
+ /// Return any dependencies that synthetic symbols (e.g. init symbols)
+ /// have on locally scoped jitlink::Symbols. This is used by the
+ /// ObjectLinkingLayer to update the dependencies for the synthetic
+ /// symbols.
+ virtual LocalDependenciesMap
+ getSyntheticSymbolLocalDependencies(MaterializationResponsibility &MR) {
+ return LocalDependenciesMap();
}
- virtual Error notifyRemovingAllModules() { return Error::success(); }
};
- /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
- /// and NotifyEmitted functors.
+ using ReturnObjectBufferFunction =
+ std::function<void(std::unique_ptr<MemoryBuffer>)>;
+
+ /// Construct an ObjectLinkingLayer.
ObjectLinkingLayer(ExecutionSession &ES,
jitlink::JITLinkMemoryManager &MemMgr);
+ /// Construct an ObjectLinkingLayer. Takes ownership of the given
+ /// JITLinkMemoryManager. This method is a temporary hack to simplify
+ /// co-existence with RTDyldObjectLinkingLayer (which also owns its
+ /// allocators).
+ ObjectLinkingLayer(ExecutionSession &ES,
+ std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
+
/// Destruct an ObjectLinkingLayer.
~ObjectLinkingLayer();
+ /// Set an object buffer return function. By default object buffers are
+ /// deleted once the JIT has linked them. If a return function is set then
+ /// it will be called to transfer ownership of the buffer instead.
+ void setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer) {
+ this->ReturnObjectBuffer = std::move(ReturnObjectBuffer);
+ }
+
/// Add a pass-config modifier.
ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) {
std::lock_guard<std::mutex> Lock(LayerMutex);
@@ -88,10 +119,14 @@
return *this;
}
- /// Emit the object.
- void emit(MaterializationResponsibility R,
+ /// Emit an object file.
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) override;
+ /// Emit a LinkGraph.
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
+ std::unique_ptr<jitlink::LinkGraph> G);
+
/// Instructs this ObjectLinkingLayer instance to override the symbol flags
/// found in the AtomGraph with the flags supplied by the
/// MaterializationResponsibility instance. This is a workaround to support
@@ -131,32 +166,44 @@
void notifyLoaded(MaterializationResponsibility &MR);
Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
- Error removeModule(VModuleKey K);
- Error removeAllModules();
+ Error handleRemoveResources(ResourceKey K) override;
+ void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
mutable std::mutex LayerMutex;
jitlink::JITLinkMemoryManager &MemMgr;
+ std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership;
bool OverrideObjectFlags = false;
bool AutoClaimObjectSymbols = false;
- DenseMap<VModuleKey, AllocPtr> TrackedAllocs;
- std::vector<AllocPtr> UntrackedAllocs;
+ ReturnObjectBufferFunction ReturnObjectBuffer;
+ DenseMap<ResourceKey, std::vector<AllocPtr>> Allocs;
std::vector<std::unique_ptr<Plugin>> Plugins;
};
class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
public:
- EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar);
- Error notifyEmitted(MaterializationResponsibility &MR) override;
+ EHFrameRegistrationPlugin(
+ ExecutionSession &ES,
+ std::unique_ptr<jitlink::EHFrameRegistrar> Registrar);
void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
jitlink::PassConfiguration &PassConfig) override;
- Error notifyRemovingModule(VModuleKey K) override;
- Error notifyRemovingAllModules() override;
+ Error notifyEmitted(MaterializationResponsibility &MR) override;
+ Error notifyFailed(MaterializationResponsibility &MR) override;
+ Error notifyRemovingResources(ResourceKey K) override;
+ void notifyTransferringResources(ResourceKey DstKey,
+ ResourceKey SrcKey) override;
private:
- jitlink::EHFrameRegistrar &Registrar;
- DenseMap<MaterializationResponsibility *, JITTargetAddress> InProcessLinks;
- DenseMap<VModuleKey, JITTargetAddress> TrackedEHFrameAddrs;
- std::vector<JITTargetAddress> UntrackedEHFrameAddrs;
+
+ struct EHFrameRange {
+ JITTargetAddress Addr = 0;
+ size_t Size;
+ };
+
+ std::mutex EHFramePluginMutex;
+ ExecutionSession &ES;
+ std::unique_ptr<jitlink::EHFrameRegistrar> Registrar;
+ DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks;
+ DenseMap<ResourceKey, std::vector<EHFrameRange>> EHFrameRanges;
};
} // end namespace orc
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
index de4603f..d8395ab 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
@@ -29,84 +29,20 @@
std::unique_ptr<MemoryBuffer>)>;
ObjectTransformLayer(ExecutionSession &ES, ObjectLayer &BaseLayer,
- TransformFunction Transform);
+ TransformFunction Transform = TransformFunction());
- void emit(MaterializationResponsibility R,
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) override;
+ void setTransform(TransformFunction Transform) {
+ this->Transform = std::move(Transform);
+ }
+
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
-/// the set of transformed objects to the layer below.
-template <typename BaseLayerT, typename TransformFtor>
-class LegacyObjectTransformLayer {
-public:
- /// Construct an ObjectTransformLayer with the given BaseLayer
- LegacyObjectTransformLayer(BaseLayerT &BaseLayer,
- TransformFtor Transform = TransformFtor())
- : BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
-
- /// 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.
- ///
- /// @return A handle for the added objects.
- template <typename ObjectPtr> Error addObject(VModuleKey K, ObjectPtr Obj) {
- return BaseLayer.addObject(std::move(K), Transform(std::move(Obj)));
- }
-
- /// Remove the object set associated with the VModuleKey K.
- Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); }
-
- /// 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.
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
- }
-
- /// 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.
- /// @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 is found in the
- /// given object set.
- JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) {
- return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
- }
-
- /// Immediately emit and finalize the object set represented by the
- /// given VModuleKey K.
- Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
-
- /// 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);
- }
-
- /// Access the transform functor directly.
- TransformFtor &getTransform() { return Transform; }
-
- /// Access the mumate functor directly.
- const TransformFtor &getTransform() const { return Transform; }
-
-private:
- BaseLayerT &BaseLayer;
- TransformFtor Transform;
-};
-
} // end namespace orc
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
index 38246bc..5061c15 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
@@ -20,128 +20,107 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Memory.h"
+#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cstdint>
namespace llvm {
namespace orc {
+struct IndirectStubsAllocationSizes {
+ uint64_t StubBytes = 0;
+ uint64_t PointerBytes = 0;
+ unsigned NumStubs = 0;
+};
+
+template <typename ORCABI>
+IndirectStubsAllocationSizes
+getIndirectStubsBlockSizes(unsigned MinStubs, unsigned RoundToMultipleOf = 0) {
+ assert(
+ (RoundToMultipleOf == 0 || (RoundToMultipleOf % ORCABI::StubSize == 0)) &&
+ "RoundToMultipleOf is not a multiple of stub size");
+ uint64_t StubBytes = MinStubs * ORCABI::StubSize;
+ if (RoundToMultipleOf)
+ StubBytes = alignTo(StubBytes, RoundToMultipleOf);
+ unsigned NumStubs = StubBytes / ORCABI::StubSize;
+ uint64_t PointerBytes = NumStubs * ORCABI::PointerSize;
+ return {StubBytes, PointerBytes, NumStubs};
+}
+
/// Generic ORC ABI support.
///
-/// This class can be substituted as the target architecure support class for
+/// This class can be substituted as the target architecture support class for
/// ORC templates that require one (e.g. IndirectStubsManagers). It does not
/// support lazy JITing however, and any attempt to use that functionality
/// will result in execution of an llvm_unreachable.
class OrcGenericABI {
public:
- static const unsigned PointerSize = sizeof(uintptr_t);
- static const unsigned TrampolineSize = 1;
- static const unsigned ResolverCodeSize = 1;
+ static constexpr unsigned PointerSize = sizeof(uintptr_t);
+ static constexpr unsigned TrampolineSize = 1;
+ static constexpr unsigned StubSize = 1;
+ static constexpr unsigned StubToPointerMaxDisplacement = 1;
+ static constexpr unsigned ResolverCodeSize = 1;
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
-
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
- void *CallbackMgr) {
+ static void writeResolverCode(char *ResolveWorkingMem,
+ JITTargetAddress ResolverTargetAddr,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) {
llvm_unreachable("writeResolverCode is not supported by the generic host "
"support class");
}
- static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
+ static void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddr,
+ JITTargetAddress ResolverAddr,
unsigned NumTrampolines) {
llvm_unreachable("writeTrampolines is not supported by the generic host "
"support class");
}
- class IndirectStubsInfo {
- public:
- const static unsigned StubSize = 1;
-
- unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
- void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
- void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
- };
-
- static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
- unsigned MinStubs, void *InitialPtrVal) {
- llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
- "host support class");
+ static void writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
+ llvm_unreachable(
+ "writeIndirectStubsBlock is not supported by the generic host "
+ "support class");
}
};
-/// Provide information about stub blocks generated by the
-/// makeIndirectStubsBlock function.
-template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
-public:
- const static unsigned StubSize = StubSizeVal;
-
- GenericIndirectStubsInfo() = default;
- GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
- : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
- GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other)
- : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
- Other.NumStubs = 0;
- }
-
- GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
- NumStubs = Other.NumStubs;
- Other.NumStubs = 0;
- StubsMem = std::move(Other.StubsMem);
- return *this;
- }
-
- /// Number of stubs in this block.
- unsigned getNumStubs() const { return NumStubs; }
-
- /// 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;
- }
-
- /// 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;
- return reinterpret_cast<void **>(PtrsBase) + Idx;
- }
-
-private:
- unsigned NumStubs = 0;
- sys::OwningMemoryBlock StubsMem;
-};
-
class OrcAArch64 {
public:
- static const unsigned PointerSize = 8;
- static const unsigned TrampolineSize = 12;
- static const unsigned ResolverCodeSize = 0x120;
+ static constexpr unsigned PointerSize = 8;
+ static constexpr unsigned TrampolineSize = 12;
+ static constexpr unsigned StubSize = 8;
+ static constexpr unsigned StubToPointerMaxDisplacement = 1U << 27;
+ static constexpr unsigned ResolverCodeSize = 0x120;
- using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
+ /// Write the resolver code into the given memory. The user is
+ /// responsible for allocating the memory and setting permissions.
+ ///
+ /// ReentryFnAddr should be the address of a function whose signature matches
+ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
+ /// argument of writeResolverCode will be passed as the second argument to
+ /// the function at ReentryFnAddr.
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress RentryCtxAddr);
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
-
- /// 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);
-
- /// 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,
+ /// Write the requested number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddress,
+ JITTargetAddress ResolverAddr,
unsigned NumTrampolines);
- /// 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
- /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
- /// will return a block of 1024 (2-pages worth).
- static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
- unsigned MinStubs, void *InitialPtrVal);
+ /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
+ /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
+ /// Nth stub using the Nth pointer in memory starting at
+ /// PointersBlockTargetAddress.
+ static void writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned MinStubs);
};
/// X86_64 code that's common to all ABIs.
@@ -149,25 +128,26 @@
/// X86_64 supports lazy JITing.
class OrcX86_64_Base {
public:
- static const unsigned PointerSize = 8;
- static const unsigned TrampolineSize = 8;
+ static constexpr unsigned PointerSize = 8;
+ static constexpr unsigned TrampolineSize = 8;
+ static constexpr unsigned StubSize = 8;
+ static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
- using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
-
- /// 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,
+ /// Write the requested number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddress,
+ JITTargetAddress ResolverAddr,
unsigned NumTrampolines);
- /// 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
- /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
- /// will return a block of 1024 (2-pages worth).
- static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
- unsigned MinStubs, void *InitialPtrVal);
+ /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
+ /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
+ /// Nth stub using the Nth pointer in memory starting at
+ /// PointersBlockTargetAddress.
+ static void writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
};
/// X86_64 support for SysV ABI (Linux, MacOSX).
@@ -175,15 +155,19 @@
/// X86_64_SysV supports lazy JITing.
class OrcX86_64_SysV : public OrcX86_64_Base {
public:
- static const unsigned ResolverCodeSize = 0x6C;
+ static constexpr unsigned ResolverCodeSize = 0x6C;
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
-
- /// 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);
+ /// Write the resolver code into the given memory. The user is
+ /// responsible for allocating the memory and setting permissions.
+ ///
+ /// ReentryFnAddr should be the address of a function whose signature matches
+ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
+ /// argument of writeResolverCode will be passed as the second argument to
+ /// the function at ReentryFnAddr.
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr);
};
/// X86_64 support for Win32.
@@ -191,15 +175,19 @@
/// X86_64_Win32 supports lazy JITing.
class OrcX86_64_Win32 : public OrcX86_64_Base {
public:
- static const unsigned ResolverCodeSize = 0x74;
+ static constexpr unsigned ResolverCodeSize = 0x74;
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
-
- /// 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);
+ /// Write the resolver code into the given memory. The user is
+ /// responsible for allocating the memory and setting permissions.
+ ///
+ /// ReentryFnAddr should be the address of a function whose signature matches
+ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
+ /// argument of writeResolverCode will be passed as the second argument to
+ /// the function at ReentryFnAddr.
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr);
};
/// I386 support.
@@ -207,34 +195,39 @@
/// I386 supports lazy JITing.
class OrcI386 {
public:
- static const unsigned PointerSize = 4;
- static const unsigned TrampolineSize = 8;
- static const unsigned ResolverCodeSize = 0x4a;
+ static constexpr unsigned PointerSize = 4;
+ static constexpr unsigned TrampolineSize = 8;
+ static constexpr unsigned StubSize = 8;
+ static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
+ static constexpr unsigned ResolverCodeSize = 0x4a;
- using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
+ /// Write the resolver code into the given memory. The user is
+ /// responsible for allocating the memory and setting permissions.
+ ///
+ /// ReentryFnAddr should be the address of a function whose signature matches
+ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
+ /// argument of writeResolverCode will be passed as the second argument to
+ /// the function at ReentryFnAddr.
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr);
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
-
- /// 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);
-
- /// 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,
+ /// Write the requested number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddress,
+ JITTargetAddress ResolverAddr,
unsigned NumTrampolines);
- /// 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
- /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
- /// will return a block of 1024 (2-pages worth).
- static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
- unsigned MinStubs, void *InitialPtrVal);
+ /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
+ /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
+ /// Nth stub using the Nth pointer in memory starting at
+ /// PointersBlockTargetAddress.
+ static void writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
};
// @brief Mips32 support.
@@ -242,41 +235,61 @@
// Mips32 supports lazy JITing.
class OrcMips32_Base {
public:
- static const unsigned PointerSize = 4;
- static const unsigned TrampolineSize = 20;
- static const unsigned ResolverCodeSize = 0xfc;
- using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
+ static constexpr unsigned PointerSize = 4;
+ static constexpr unsigned TrampolineSize = 20;
+ static constexpr unsigned StubSize = 8;
+ static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
+ static constexpr unsigned ResolverCodeSize = 0xfc;
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
- /// @brief Write the requsted number of trampolines into the given memory,
- /// which must be big enough to hold 1 pointer, plus NumTrampolines
- /// trampolines.
- static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
+ /// Write the requested number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddress,
+ JITTargetAddress ResolverAddr,
+ unsigned NumTrampolines);
- /// @brief Write the resolver code into the given memory. The user is be
- /// responsible for allocating the memory and setting permissions.
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian);
- /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
- /// the nearest page size.
+ /// Write the resolver code into the given memory. The user is
+ /// responsible for allocating the memory and setting permissions.
///
- /// E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k
- /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
- /// will return a block of 1024 (2-pages worth).
- static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
+ /// ReentryFnAddr should be the address of a function whose signature matches
+ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
+ /// argument of writeResolverCode will be passed as the second argument to
+ /// the function at ReentryFnAddr.
+ static void writeResolverCode(char *ResolverBlockWorkingMem,
+ JITTargetAddress ResolverBlockTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr,
+ bool isBigEndian);
+ /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
+ /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
+ /// Nth stub using the Nth pointer in memory starting at
+ /// PointersBlockTargetAddress.
+ static void writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
};
-
class OrcMips32Le : public OrcMips32_Base {
public:
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
- { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) {
+ OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress,
+ ReentryFnAddr, ReentryCtxAddr, false);
+ }
};
class OrcMips32Be : public OrcMips32_Base {
public:
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
- { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) {
+ OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress,
+ ReentryFnAddr, ReentryCtxAddr, true);
+ }
};
// @brief Mips64 support.
@@ -284,31 +297,41 @@
// Mips64 supports lazy JITing.
class OrcMips64 {
public:
- static const unsigned PointerSize = 8;
- static const unsigned TrampolineSize = 40;
- static const unsigned ResolverCodeSize = 0x120;
+ static constexpr unsigned PointerSize = 8;
+ static constexpr unsigned TrampolineSize = 40;
+ static constexpr unsigned StubSize = 32;
+ static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
+ static constexpr unsigned ResolverCodeSize = 0x120;
- using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
- using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
- void *TrampolineId);
- /// @brief Write the resolver code into the given memory. The user is be
- /// responsible for allocating the memory and setting permissions.
- static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr);
-
- /// @brief Write the requsted number of trampolines into the given memory,
- /// which must be big enough to hold 1 pointer, plus NumTrampolines
- /// trampolines.
- static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
-
- /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
- /// the nearest page size.
+ /// Write the resolver code into the given memory. The user is
+ /// responsible for allocating the memory and setting permissions.
///
- /// E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k
- /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
- /// will return a block of 1024 (2-pages worth).
- static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
+ /// ReentryFnAddr should be the address of a function whose signature matches
+ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
+ /// argument of writeResolverCode will be passed as the second argument to
+ /// the function at ReentryFnAddr.
+ static void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddress,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr);
+
+ /// Write the requested number of trampolines into the given memory,
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines
+ /// trampolines.
+ static void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddress,
+ JITTargetAddress ResolverFnAddr,
+ unsigned NumTrampolines);
+ /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
+ /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
+ /// Nth stub using the Nth pointer in memory starting at
+ /// PointersBlockTargetAddress.
+ static void writeIndirectStubsBlock(
+ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
};
- } // end namespace orc
- } // end namespace llvm
+} // end namespace orc
+} // end namespace llvm
+
#endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
index e5d6a3e..9b0d941 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -14,6 +14,8 @@
#define LLVM_EXECUTIONENGINE_ORC_ORCERROR_H
#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
#include <system_error>
namespace llvm {
@@ -35,7 +37,9 @@
UnexpectedRPCCall,
UnexpectedRPCResponse,
UnknownErrorCodeFromRemote,
- UnknownResourceHandle
+ UnknownResourceHandle,
+ MissingSymbolDefinitions,
+ UnexpectedSymbolDefinitions,
};
std::error_code orcError(OrcErrorCode ErrCode);
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
new file mode 100644
index 0000000..1097ae6
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
@@ -0,0 +1,415 @@
+//===--- OrcRPCTargetProcessControl.h - Remote target control ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for interacting with target processes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
+#define LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
+
+#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+
+namespace llvm {
+namespace orc {
+
+/// JITLinkMemoryManager implementation for a process connected via an ORC RPC
+/// endpoint.
+template <typename OrcRPCTPCImplT>
+class OrcRPCTPCJITLinkMemoryManager : public jitlink::JITLinkMemoryManager {
+private:
+ struct HostAlloc {
+ std::unique_ptr<char[]> Mem;
+ uint64_t Size;
+ };
+
+ struct TargetAlloc {
+ JITTargetAddress Address = 0;
+ uint64_t AllocatedSize = 0;
+ };
+
+ using HostAllocMap = DenseMap<int, HostAlloc>;
+ using TargetAllocMap = DenseMap<int, TargetAlloc>;
+
+public:
+ class OrcRPCAllocation : public Allocation {
+ public:
+ OrcRPCAllocation(OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent,
+ HostAllocMap HostAllocs, TargetAllocMap TargetAllocs)
+ : Parent(Parent), HostAllocs(std::move(HostAllocs)),
+ TargetAllocs(std::move(TargetAllocs)) {
+ assert(HostAllocs.size() == TargetAllocs.size() &&
+ "HostAllocs size should match TargetAllocs");
+ }
+
+ ~OrcRPCAllocation() override {
+ assert(TargetAllocs.empty() && "failed to deallocate");
+ }
+
+ MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
+ auto I = HostAllocs.find(Seg);
+ assert(I != HostAllocs.end() && "No host allocation for segment");
+ auto &HA = I->second;
+ return {HA.Mem.get(), static_cast<size_t>(HA.Size)};
+ }
+
+ JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
+ auto I = TargetAllocs.find(Seg);
+ assert(I != TargetAllocs.end() && "No target allocation for segment");
+ return I->second.Address;
+ }
+
+ void finalizeAsync(FinalizeContinuation OnFinalize) override {
+
+ std::vector<tpctypes::BufferWrite> BufferWrites;
+ orcrpctpc::ReleaseOrFinalizeMemRequest FMR;
+
+ for (auto &KV : HostAllocs) {
+ assert(TargetAllocs.count(KV.first) &&
+ "No target allocation for buffer");
+ auto &HA = KV.second;
+ auto &TA = TargetAllocs[KV.first];
+ BufferWrites.push_back({TA.Address, StringRef(HA.Mem.get(), HA.Size)});
+ FMR.push_back({orcrpctpc::toWireProtectionFlags(
+ static_cast<sys::Memory::ProtectionFlags>(KV.first)),
+ TA.Address, TA.AllocatedSize});
+ }
+
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "finalizeAsync " << (void *)this << ":\n";
+ auto FMRI = FMR.begin();
+ for (auto &B : BufferWrites) {
+ auto Prot = FMRI->Prot;
+ ++FMRI;
+ dbgs() << " Writing " << formatv("{0:x16}", B.Buffer.size())
+ << " bytes to " << ((Prot & orcrpctpc::WPF_Read) ? 'R' : '-')
+ << ((Prot & orcrpctpc::WPF_Write) ? 'W' : '-')
+ << ((Prot & orcrpctpc::WPF_Exec) ? 'X' : '-')
+ << " segment: local " << (const void *)B.Buffer.data()
+ << " -> target " << formatv("{0:x16}", B.Address) << "\n";
+ }
+ });
+ if (auto Err =
+ Parent.Parent.getMemoryAccess().writeBuffers(BufferWrites)) {
+ OnFinalize(std::move(Err));
+ return;
+ }
+
+ DEBUG_WITH_TYPE("orc", dbgs() << " Applying permissions...\n");
+ if (auto Err =
+ Parent.getEndpoint().template callAsync<orcrpctpc::FinalizeMem>(
+ [OF = std::move(OnFinalize)](Error Err2) {
+ // FIXME: Dispatch to work queue.
+ std::thread([OF = std::move(OF),
+ Err3 = std::move(Err2)]() mutable {
+ DEBUG_WITH_TYPE(
+ "orc", { dbgs() << " finalizeAsync complete\n"; });
+ OF(std::move(Err3));
+ }).detach();
+ return Error::success();
+ },
+ FMR)) {
+ DEBUG_WITH_TYPE("orc", dbgs() << " failed.\n");
+ Parent.getEndpoint().abandonPendingResponses();
+ Parent.reportError(std::move(Err));
+ }
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Leaving finalizeAsync (finalization may continue in "
+ "background)\n";
+ });
+ }
+
+ Error deallocate() override {
+ orcrpctpc::ReleaseOrFinalizeMemRequest RMR;
+ for (auto &KV : TargetAllocs)
+ RMR.push_back({orcrpctpc::toWireProtectionFlags(
+ static_cast<sys::Memory::ProtectionFlags>(KV.first)),
+ KV.second.Address, KV.second.AllocatedSize});
+ TargetAllocs.clear();
+
+ return Parent.getEndpoint().template callB<orcrpctpc::ReleaseMem>(RMR);
+ }
+
+ private:
+ OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent;
+ HostAllocMap HostAllocs;
+ TargetAllocMap TargetAllocs;
+ };
+
+ OrcRPCTPCJITLinkMemoryManager(OrcRPCTPCImplT &Parent) : Parent(Parent) {}
+
+ Expected<std::unique_ptr<Allocation>>
+ allocate(const jitlink::JITLinkDylib *JD,
+ const SegmentsRequestMap &Request) override {
+ orcrpctpc::ReserveMemRequest RMR;
+ HostAllocMap HostAllocs;
+
+ for (auto &KV : Request) {
+ assert(KV.second.getContentSize() <= std::numeric_limits<size_t>::max() &&
+ "Content size is out-of-range for host");
+
+ RMR.push_back({orcrpctpc::toWireProtectionFlags(
+ static_cast<sys::Memory::ProtectionFlags>(KV.first)),
+ KV.second.getContentSize() + KV.second.getZeroFillSize(),
+ KV.second.getAlignment()});
+ HostAllocs[KV.first] = {
+ std::make_unique<char[]>(KV.second.getContentSize()),
+ KV.second.getContentSize()};
+ }
+
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Orc remote memmgr got request:\n";
+ for (auto &KV : Request)
+ dbgs() << " permissions: "
+ << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-')
+ << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-')
+ << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-')
+ << ", content size: "
+ << formatv("{0:x16}", KV.second.getContentSize())
+ << " + zero-fill-size: "
+ << formatv("{0:x16}", KV.second.getZeroFillSize())
+ << ", align: " << KV.second.getAlignment() << "\n";
+ });
+
+ // FIXME: LLVM RPC needs to be fixed to support alt
+ // serialization/deserialization on return types. For now just
+ // translate from std::map to DenseMap manually.
+ auto TmpTargetAllocs =
+ Parent.getEndpoint().template callB<orcrpctpc::ReserveMem>(RMR);
+ if (!TmpTargetAllocs)
+ return TmpTargetAllocs.takeError();
+
+ if (TmpTargetAllocs->size() != RMR.size())
+ return make_error<StringError>(
+ "Number of target allocations does not match request",
+ inconvertibleErrorCode());
+
+ TargetAllocMap TargetAllocs;
+ for (auto &E : *TmpTargetAllocs)
+ TargetAllocs[orcrpctpc::fromWireProtectionFlags(E.Prot)] = {
+ E.Address, E.AllocatedSize};
+
+ DEBUG_WITH_TYPE("orc", {
+ auto HAI = HostAllocs.begin();
+ for (auto &KV : TargetAllocs)
+ dbgs() << " permissions: "
+ << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-')
+ << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-')
+ << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-')
+ << " assigned local " << (void *)HAI->second.Mem.get()
+ << ", target " << formatv("{0:x16}", KV.second.Address) << "\n";
+ });
+
+ return std::make_unique<OrcRPCAllocation>(*this, std::move(HostAllocs),
+ std::move(TargetAllocs));
+ }
+
+private:
+ void reportError(Error Err) { Parent.reportError(std::move(Err)); }
+
+ decltype(std::declval<OrcRPCTPCImplT>().getEndpoint()) getEndpoint() {
+ return Parent.getEndpoint();
+ }
+
+ OrcRPCTPCImplT &Parent;
+};
+
+/// TargetProcessControl::MemoryAccess implementation for a process connected
+/// via an ORC RPC endpoint.
+template <typename OrcRPCTPCImplT>
+class OrcRPCTPCMemoryAccess : public TargetProcessControl::MemoryAccess {
+public:
+ OrcRPCTPCMemoryAccess(OrcRPCTPCImplT &Parent) : Parent(Parent) {}
+
+ void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ writeViaRPC<orcrpctpc::WriteUInt8s>(Ws, std::move(OnWriteComplete));
+ }
+
+ void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ writeViaRPC<orcrpctpc::WriteUInt16s>(Ws, std::move(OnWriteComplete));
+ }
+
+ void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ writeViaRPC<orcrpctpc::WriteUInt32s>(Ws, std::move(OnWriteComplete));
+ }
+
+ void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
+ WriteResultFn OnWriteComplete) override {
+ writeViaRPC<orcrpctpc::WriteUInt64s>(Ws, std::move(OnWriteComplete));
+ }
+
+ void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
+ WriteResultFn OnWriteComplete) override {
+ writeViaRPC<orcrpctpc::WriteBuffers>(Ws, std::move(OnWriteComplete));
+ }
+
+private:
+ template <typename WriteRPCFunction, typename WriteElementT>
+ void writeViaRPC(ArrayRef<WriteElementT> Ws, WriteResultFn OnWriteComplete) {
+ if (auto Err = Parent.getEndpoint().template callAsync<WriteRPCFunction>(
+ [OWC = std::move(OnWriteComplete)](Error Err2) mutable -> Error {
+ OWC(std::move(Err2));
+ return Error::success();
+ },
+ Ws)) {
+ Parent.reportError(std::move(Err));
+ Parent.getEndpoint().abandonPendingResponses();
+ }
+ }
+
+ OrcRPCTPCImplT &Parent;
+};
+
+// TargetProcessControl for a process connected via an ORC RPC Endpoint.
+template <typename RPCEndpointT>
+class OrcRPCTargetProcessControlBase : public TargetProcessControl {
+public:
+ using ErrorReporter = unique_function<void(Error)>;
+
+ using OnCloseConnectionFunction = unique_function<Error(Error)>;
+
+ OrcRPCTargetProcessControlBase(std::shared_ptr<SymbolStringPool> SSP,
+ RPCEndpointT &EP, ErrorReporter ReportError)
+ : TargetProcessControl(std::move(SSP)),
+ ReportError(std::move(ReportError)), EP(EP) {}
+
+ void reportError(Error Err) { ReportError(std::move(Err)); }
+
+ RPCEndpointT &getEndpoint() { return EP; }
+
+ Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Loading dylib \"" << (DylibPath ? DylibPath : "") << "\" ";
+ if (!DylibPath)
+ dbgs() << "(process symbols)";
+ dbgs() << "\n";
+ });
+ if (!DylibPath)
+ DylibPath = "";
+ auto H = EP.template callB<orcrpctpc::LoadDylib>(DylibPath);
+ DEBUG_WITH_TYPE("orc", {
+ if (H)
+ dbgs() << " got handle " << formatv("{0:x16}", *H) << "\n";
+ else
+ dbgs() << " error, unable to load\n";
+ });
+ return H;
+ }
+
+ Expected<std::vector<tpctypes::LookupResult>>
+ lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) override {
+ std::vector<orcrpctpc::RemoteLookupRequest> RR;
+ for (auto &E : Request) {
+ RR.push_back({});
+ RR.back().first = E.Handle;
+ for (auto &KV : E.Symbols)
+ RR.back().second.push_back(
+ {(*KV.first).str(),
+ KV.second == SymbolLookupFlags::WeaklyReferencedSymbol});
+ }
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Compound lookup:\n";
+ for (auto &R : Request) {
+ dbgs() << " In " << formatv("{0:x16}", R.Handle) << ": {";
+ bool First = true;
+ for (auto &KV : R.Symbols) {
+ dbgs() << (First ? "" : ",") << " " << *KV.first;
+ First = false;
+ }
+ dbgs() << " }\n";
+ }
+ });
+ return EP.template callB<orcrpctpc::LookupSymbols>(RR);
+ }
+
+ Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
+ ArrayRef<std::string> Args) override {
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Running as main: " << formatv("{0:x16}", MainFnAddr)
+ << ", args = [";
+ for (unsigned I = 0; I != Args.size(); ++I)
+ dbgs() << (I ? "," : "") << " \"" << Args[I] << "\"";
+ dbgs() << "]\n";
+ });
+ auto Result = EP.template callB<orcrpctpc::RunMain>(MainFnAddr, Args);
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << " call to " << formatv("{0:x16}", MainFnAddr);
+ if (Result)
+ dbgs() << " returned result " << *Result << "\n";
+ else
+ dbgs() << " failed\n";
+ });
+ return Result;
+ }
+
+ Expected<tpctypes::WrapperFunctionResult>
+ runWrapper(JITTargetAddress WrapperFnAddr,
+ ArrayRef<uint8_t> ArgBuffer) override {
+ DEBUG_WITH_TYPE("orc", {
+ dbgs() << "Running as wrapper function "
+ << formatv("{0:x16}", WrapperFnAddr) << " with "
+ << formatv("{0:x16}", ArgBuffer.size()) << " argument buffer\n";
+ });
+ auto Result =
+ EP.template callB<orcrpctpc::RunWrapper>(WrapperFnAddr, ArgBuffer);
+ // dbgs() << "Returned from runWrapper...\n";
+ return Result;
+ }
+
+ Error closeConnection(OnCloseConnectionFunction OnCloseConnection) {
+ DEBUG_WITH_TYPE("orc", dbgs() << "Closing connection to remote\n");
+ return EP.template callAsync<orcrpctpc::CloseConnection>(
+ std::move(OnCloseConnection));
+ }
+
+ Error closeConnectionAndWait() {
+ std::promise<MSVCPError> P;
+ auto F = P.get_future();
+ if (auto Err = closeConnection([&](Error Err2) -> Error {
+ P.set_value(std::move(Err2));
+ return Error::success();
+ })) {
+ EP.abandonAllPendingResponses();
+ return joinErrors(std::move(Err), F.get());
+ }
+ return F.get();
+ }
+
+protected:
+ /// Subclasses must call this during construction to initialize the
+ /// TargetTriple and PageSize members.
+ Error initializeORCRPCTPCBase() {
+ if (auto TripleOrErr = EP.template callB<orcrpctpc::GetTargetTriple>())
+ TargetTriple = Triple(*TripleOrErr);
+ else
+ return TripleOrErr.takeError();
+
+ if (auto PageSizeOrErr = EP.template callB<orcrpctpc::GetPageSize>())
+ PageSize = *PageSizeOrErr;
+ else
+ return PageSizeOrErr.takeError();
+
+ return Error::success();
+ }
+
+private:
+ ErrorReporter ReportError;
+ RPCEndpointT &EP;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 8b875b7..3d13974 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
@@ -53,7 +54,7 @@
/// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
/// its actions.
class OrcRemoteTargetClient
- : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
+ : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> {
public:
/// Remote-mapped RuntimeDyld-compatible memory manager.
class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
@@ -329,6 +330,221 @@
std::vector<EHFrame> RegisteredEHFrames;
};
+ class RPCMMAlloc : public jitlink::JITLinkMemoryManager::Allocation {
+ using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
+ using FinalizeContinuation =
+ jitlink::JITLinkMemoryManager::Allocation::FinalizeContinuation;
+ using ProtectionFlags = sys::Memory::ProtectionFlags;
+ using SegmentsRequestMap =
+ DenseMap<unsigned, jitlink::JITLinkMemoryManager::SegmentRequest>;
+
+ RPCMMAlloc(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id)
+ : Client(Client), Id(Id) {}
+
+ public:
+ static Expected<std::unique_ptr<RPCMMAlloc>>
+ Create(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id,
+ const SegmentsRequestMap &Request) {
+ auto *MM = new RPCMMAlloc(Client, Id);
+
+ if (Error Err = MM->allocateHostBlocks(Request))
+ return std::move(Err);
+
+ if (Error Err = MM->allocateTargetBlocks())
+ return std::move(Err);
+
+ return std::unique_ptr<RPCMMAlloc>(MM);
+ }
+
+ MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
+ assert(HostSegBlocks.count(Seg) && "No allocation for segment");
+ return {static_cast<char *>(HostSegBlocks[Seg].base()),
+ HostSegBlocks[Seg].allocatedSize()};
+ }
+
+ JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
+ assert(TargetSegBlocks.count(Seg) && "No allocation for segment");
+ return pointerToJITTargetAddress(TargetSegBlocks[Seg].base());
+ }
+
+ void finalizeAsync(FinalizeContinuation OnFinalize) override {
+ // Host allocations (working memory) remain ReadWrite.
+ OnFinalize(copyAndProtect());
+ }
+
+ Error deallocate() override {
+ // TODO: Cannot release target allocation. RPCAPI has no function
+ // symmetric to reserveMem(). Add RPC call like freeMem()?
+ return errorCodeToError(sys::Memory::releaseMappedMemory(HostAllocation));
+ }
+
+ private:
+ OrcRemoteTargetClient &Client;
+ ResourceIdMgr::ResourceId Id;
+ AllocationMap HostSegBlocks;
+ AllocationMap TargetSegBlocks;
+ JITTargetAddress TargetSegmentAddr;
+ sys::MemoryBlock HostAllocation;
+
+ Error allocateHostBlocks(const SegmentsRequestMap &Request) {
+ unsigned TargetPageSize = Client.getPageSize();
+
+ if (!isPowerOf2_64(static_cast<uint64_t>(TargetPageSize)))
+ return make_error<StringError>("Host page size is not a power of 2",
+ inconvertibleErrorCode());
+
+ auto TotalSize = calcTotalAllocSize(Request, TargetPageSize);
+ if (!TotalSize)
+ return TotalSize.takeError();
+
+ // Allocate one slab to cover all the segments.
+ const sys::Memory::ProtectionFlags ReadWrite =
+ static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE);
+ std::error_code EC;
+ HostAllocation =
+ sys::Memory::allocateMappedMemory(*TotalSize, nullptr, ReadWrite, EC);
+ if (EC)
+ return errorCodeToError(EC);
+
+ char *SlabAddr = static_cast<char *>(HostAllocation.base());
+#ifndef NDEBUG
+ char *SlabAddrEnd = SlabAddr + HostAllocation.allocatedSize();
+#endif
+
+ // Allocate segment memory from the slab.
+ for (auto &KV : Request) {
+ const auto &Seg = KV.second;
+
+ uint64_t SegmentSize = Seg.getContentSize() + Seg.getZeroFillSize();
+ uint64_t AlignedSegmentSize = alignTo(SegmentSize, TargetPageSize);
+
+ // Zero out zero-fill memory.
+ char *ZeroFillBegin = SlabAddr + Seg.getContentSize();
+ memset(ZeroFillBegin, 0, Seg.getZeroFillSize());
+
+ // Record the block for this segment.
+ HostSegBlocks[KV.first] =
+ sys::MemoryBlock(SlabAddr, AlignedSegmentSize);
+
+ SlabAddr += AlignedSegmentSize;
+ assert(SlabAddr <= SlabAddrEnd && "Out of range");
+ }
+
+ return Error::success();
+ }
+
+ Error allocateTargetBlocks() {
+ // Reserve memory for all blocks on the target. We need as much space on
+ // the target as we allocated on the host.
+ TargetSegmentAddr = Client.reserveMem(Id, HostAllocation.allocatedSize(),
+ Client.getPageSize());
+ if (!TargetSegmentAddr)
+ return make_error<StringError>("Failed to reserve memory on the target",
+ inconvertibleErrorCode());
+
+ // Map memory blocks into the allocation, that match the host allocation.
+ JITTargetAddress TargetAllocAddr = TargetSegmentAddr;
+ for (const auto &KV : HostSegBlocks) {
+ size_t TargetAllocSize = KV.second.allocatedSize();
+
+ TargetSegBlocks[KV.first] =
+ sys::MemoryBlock(jitTargetAddressToPointer<void *>(TargetAllocAddr),
+ TargetAllocSize);
+
+ TargetAllocAddr += TargetAllocSize;
+ assert(TargetAllocAddr - TargetSegmentAddr <=
+ HostAllocation.allocatedSize() &&
+ "Out of range on target");
+ }
+
+ return Error::success();
+ }
+
+ Error copyAndProtect() {
+ unsigned Permissions = 0u;
+
+ // Copy segments one by one.
+ for (auto &KV : TargetSegBlocks) {
+ Permissions |= KV.first;
+
+ const sys::MemoryBlock &TargetBlock = KV.second;
+ const sys::MemoryBlock &HostBlock = HostSegBlocks.lookup(KV.first);
+
+ size_t TargetAllocSize = TargetBlock.allocatedSize();
+ auto TargetAllocAddr = pointerToJITTargetAddress(TargetBlock.base());
+ auto *HostAllocBegin = static_cast<const char *>(HostBlock.base());
+
+ bool CopyErr =
+ Client.writeMem(TargetAllocAddr, HostAllocBegin, TargetAllocSize);
+ if (CopyErr)
+ return createStringError(inconvertibleErrorCode(),
+ "Failed to copy %d segment to the target",
+ KV.first);
+ }
+
+ // Set permission flags for all segments at once.
+ bool ProtectErr =
+ Client.setProtections(Id, TargetSegmentAddr, Permissions);
+ if (ProtectErr)
+ return createStringError(inconvertibleErrorCode(),
+ "Failed to apply permissions for %d segment "
+ "on the target",
+ Permissions);
+ return Error::success();
+ }
+
+ static Expected<size_t>
+ calcTotalAllocSize(const SegmentsRequestMap &Request,
+ unsigned TargetPageSize) {
+ size_t TotalSize = 0;
+ for (const auto &KV : Request) {
+ const auto &Seg = KV.second;
+
+ if (Seg.getAlignment() > TargetPageSize)
+ return make_error<StringError>("Cannot request alignment higher than "
+ "page alignment on target",
+ inconvertibleErrorCode());
+
+ TotalSize = alignTo(TotalSize, TargetPageSize);
+ TotalSize += Seg.getContentSize();
+ TotalSize += Seg.getZeroFillSize();
+ }
+
+ return TotalSize;
+ }
+ };
+
+ class RemoteJITLinkMemoryManager : public jitlink::JITLinkMemoryManager {
+ public:
+ RemoteJITLinkMemoryManager(OrcRemoteTargetClient &Client,
+ ResourceIdMgr::ResourceId Id)
+ : Client(Client), Id(Id) {}
+
+ RemoteJITLinkMemoryManager(const RemoteJITLinkMemoryManager &) = delete;
+ RemoteJITLinkMemoryManager(RemoteJITLinkMemoryManager &&) = default;
+
+ RemoteJITLinkMemoryManager &
+ operator=(const RemoteJITLinkMemoryManager &) = delete;
+ RemoteJITLinkMemoryManager &
+ operator=(RemoteJITLinkMemoryManager &&) = delete;
+
+ ~RemoteJITLinkMemoryManager() {
+ Client.destroyRemoteAllocator(Id);
+ LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
+ }
+
+ Expected<std::unique_ptr<Allocation>>
+ allocate(const jitlink::JITLinkDylib *JD,
+ const SegmentsRequestMap &Request) override {
+ return RPCMMAlloc::Create(Client, Id, Request);
+ }
+
+ private:
+ OrcRemoteTargetClient &Client;
+ ResourceIdMgr::ResourceId Id;
+ };
+
/// Remote indirect stubs manager.
class RemoteIndirectStubsManager : public IndirectStubsManager {
public:
@@ -453,20 +669,8 @@
public:
RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {}
- Expected<JITTargetAddress> getTrampoline() override {
- std::lock_guard<std::mutex> Lock(RTPMutex);
- if (AvailableTrampolines.empty()) {
- if (auto Err = grow())
- return std::move(Err);
- }
- assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
- auto TrampolineAddr = AvailableTrampolines.back();
- AvailableTrampolines.pop_back();
- return TrampolineAddr;
- }
-
private:
- Error grow() {
+ Error grow() override {
JITTargetAddress BlockAddr = 0;
uint32_t NumTrampolines = 0;
if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
@@ -476,14 +680,12 @@
uint32_t TrampolineSize = Client.getTrampolineSize();
for (unsigned I = 0; I < NumTrampolines; ++I)
- this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
+ AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
return Error::success();
}
- std::mutex RTPMutex;
OrcRemoteTargetClient &Client;
- std::vector<JITTargetAddress> AvailableTrampolines;
};
/// Remote compile callback manager.
@@ -493,7 +695,7 @@
ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress)
: JITCompileCallbackManager(
- llvm::make_unique<RemoteTrampolinePool>(Client), ES,
+ std::make_unique<RemoteTrampolinePool>(Client), ES,
ErrorHandlerAddress) {}
};
@@ -501,7 +703,7 @@
/// 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, ExecutionSession &ES) {
+ Create(shared::RawByteChannel &Channel, ExecutionSession &ES) {
Error Err = Error::success();
auto Client = std::unique_ptr<OrcRemoteTargetClient>(
new OrcRemoteTargetClient(Channel, ES, Err));
@@ -518,6 +720,14 @@
return callB<exec::CallIntVoid>(Addr);
}
+ /// Call the int(int) function at the given address in the target and return
+ /// its result.
+ Expected<int> callIntInt(JITTargetAddress Addr, int Arg) {
+ LLVM_DEBUG(dbgs() << "Calling int(*)(int) " << format("0x%016" PRIx64, Addr)
+ << "\n");
+ return callB<exec::CallIntInt>(Addr, Arg);
+ }
+
/// Call the int(int, char*[]) function at the given address in the target and
/// return its result.
Expected<int> callMain(JITTargetAddress Addr,
@@ -546,6 +756,18 @@
new RemoteRTDyldMemoryManager(*this, Id));
}
+ /// Create a JITLink-compatible memory manager which will allocate working
+ /// memory on the host and target memory on the remote target.
+ Expected<std::unique_ptr<RemoteJITLinkMemoryManager>>
+ createRemoteJITLinkMemoryManager() {
+ auto Id = AllocatorIds.getNext();
+ if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
+ return std::move(Err);
+ LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
+ return std::unique_ptr<RemoteJITLinkMemoryManager>(
+ new RemoteJITLinkMemoryManager(*this, Id));
+ }
+
/// Create an RCIndirectStubsManager that will allocate stubs on the remote
/// target.
Expected<std::unique_ptr<RemoteIndirectStubsManager>>
@@ -553,7 +775,7 @@
auto Id = IndirectStubOwnerIds.getNext();
if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
return std::move(Err);
- return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
+ return std::make_unique<RemoteIndirectStubsManager>(*this, Id);
}
Expected<RemoteCompileCallbackManager &>
@@ -583,9 +805,10 @@
Error terminateSession() { return callB<utils::TerminateSession>(); }
private:
- OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
+ OrcRemoteTargetClient(shared::RawByteChannel &Channel, ExecutionSession &ES,
Error &Err)
- : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
+ : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(Channel,
+ true),
ES(ES) {
ErrorAsOutParameter EAO(&Err);
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
index e7b598d..367bfb3 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
@@ -16,8 +16,8 @@
#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
-#include "llvm/ExecutionEngine/Orc/RawByteChannel.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
namespace llvm {
namespace orc {
@@ -73,10 +73,9 @@
} // end namespace remote
-namespace rpc {
+namespace shared {
-template <>
-class RPCTypeName<JITSymbolFlags> {
+template <> class SerializationTypeName<JITSymbolFlags> {
public:
static const char *getName() { return "JITSymbolFlags"; }
};
@@ -100,7 +99,7 @@
}
};
-template <> class RPCTypeName<remote::DirectBufferWriter> {
+template <> class SerializationTypeName<remote::DirectBufferWriter> {
public:
static const char *getName() { return "DirectBufferWriter"; }
};
@@ -108,8 +107,7 @@
template <typename ChannelT>
class SerializationTraits<
ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter,
- typename std::enable_if<
- std::is_base_of<RawByteChannel, ChannelT>::value>::type> {
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
public:
static Error serialize(ChannelT &C, const remote::DirectBufferWriter &DBW) {
if (auto EC = serializeSeq(C, DBW.getDst()))
@@ -134,7 +132,7 @@
}
};
-} // end namespace rpc
+} // end namespace shared
namespace remote {
@@ -168,20 +166,20 @@
namespace eh {
/// Registers EH frames on the remote.
- class RegisterEHFrames
- : public rpc::Function<RegisterEHFrames,
- void(JITTargetAddress Addr, uint32_t Size)> {
- public:
- static const char *getName() { return "RegisterEHFrames"; }
- };
+class RegisterEHFrames
+ : public shared::RPCFunction<RegisterEHFrames,
+ void(JITTargetAddress Addr, uint32_t Size)> {
+public:
+ static const char *getName() { return "RegisterEHFrames"; }
+};
/// Deregisters EH frames on the remote.
- class DeregisterEHFrames
- : public rpc::Function<DeregisterEHFrames,
- void(JITTargetAddress Addr, uint32_t Size)> {
- public:
- static const char *getName() { return "DeregisterEHFrames"; }
- };
+class DeregisterEHFrames
+ : public shared::RPCFunction<DeregisterEHFrames,
+ void(JITTargetAddress Addr, uint32_t Size)> {
+public:
+ static const char *getName() { return "DeregisterEHFrames"; }
+};
} // end namespace eh
@@ -190,28 +188,38 @@
/// Call an 'int32_t()'-type function on the remote, returns the called
/// function's return value.
- class CallIntVoid
- : public rpc::Function<CallIntVoid, int32_t(JITTargetAddress Addr)> {
- public:
- static const char *getName() { return "CallIntVoid"; }
- };
+class CallIntVoid
+ : public shared::RPCFunction<CallIntVoid, int32_t(JITTargetAddress Addr)> {
+public:
+ static const char *getName() { return "CallIntVoid"; }
+};
+
+ /// Call an 'int32_t(int32_t)'-type function on the remote, returns the called
+ /// function's return value.
+class CallIntInt
+ : public shared::RPCFunction<CallIntInt,
+ int32_t(JITTargetAddress Addr, int)> {
+public:
+ static const char *getName() { return "CallIntInt"; }
+};
/// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the
/// called function's return value.
- class CallMain
- : public rpc::Function<CallMain, int32_t(JITTargetAddress Addr,
- std::vector<std::string> Args)> {
- public:
- static const char *getName() { return "CallMain"; }
- };
+class CallMain
+ : public shared::RPCFunction<CallMain,
+ int32_t(JITTargetAddress Addr,
+ std::vector<std::string> Args)> {
+public:
+ static const char *getName() { return "CallMain"; }
+};
/// Calls a 'void()'-type function on the remote, returns when the called
/// function completes.
- class CallVoidVoid
- : public rpc::Function<CallVoidVoid, void(JITTargetAddress FnAddr)> {
- public:
- static const char *getName() { return "CallVoidVoid"; }
- };
+class CallVoidVoid
+ : public shared::RPCFunction<CallVoidVoid, void(JITTargetAddress FnAddr)> {
+public:
+ static const char *getName() { return "CallVoidVoid"; }
+};
} // end namespace exec
@@ -219,60 +227,62 @@
namespace mem {
/// Creates a memory allocator on the remote.
- class CreateRemoteAllocator
- : public rpc::Function<CreateRemoteAllocator,
- void(ResourceIdMgr::ResourceId AllocatorID)> {
- public:
- static const char *getName() { return "CreateRemoteAllocator"; }
- };
+class CreateRemoteAllocator
+ : public shared::RPCFunction<CreateRemoteAllocator,
+ void(ResourceIdMgr::ResourceId AllocatorID)> {
+public:
+ static const char *getName() { return "CreateRemoteAllocator"; }
+};
/// Destroys a remote allocator, freeing any memory allocated by it.
- class DestroyRemoteAllocator
- : public rpc::Function<DestroyRemoteAllocator,
- void(ResourceIdMgr::ResourceId AllocatorID)> {
- public:
- static const char *getName() { return "DestroyRemoteAllocator"; }
- };
+class DestroyRemoteAllocator
+ : public shared::RPCFunction<DestroyRemoteAllocator,
+ void(ResourceIdMgr::ResourceId AllocatorID)> {
+public:
+ static const char *getName() { return "DestroyRemoteAllocator"; }
+};
/// Read a remote memory block.
- class ReadMem
- : public rpc::Function<ReadMem, std::vector<uint8_t>(JITTargetAddress Src,
- uint64_t Size)> {
- public:
- static const char *getName() { return "ReadMem"; }
- };
+class ReadMem
+ : public shared::RPCFunction<
+ ReadMem, std::vector<uint8_t>(JITTargetAddress Src, uint64_t Size)> {
+public:
+ static const char *getName() { return "ReadMem"; }
+};
/// Reserve a block of memory on the remote via the given allocator.
- class ReserveMem
- : public rpc::Function<ReserveMem,
- JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
- uint64_t Size, uint32_t Align)> {
- public:
- static const char *getName() { return "ReserveMem"; }
- };
+class ReserveMem
+ : public shared::RPCFunction<
+ ReserveMem, JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
+ uint64_t Size, uint32_t Align)> {
+public:
+ static const char *getName() { return "ReserveMem"; }
+};
/// Set the memory protection on a memory block.
- class SetProtections
- : public rpc::Function<SetProtections,
- void(ResourceIdMgr::ResourceId AllocID,
- JITTargetAddress Dst, uint32_t ProtFlags)> {
- public:
- static const char *getName() { return "SetProtections"; }
- };
+class SetProtections
+ : public shared::RPCFunction<
+ SetProtections, void(ResourceIdMgr::ResourceId AllocID,
+ JITTargetAddress Dst, uint32_t ProtFlags)> {
+public:
+ static const char *getName() { return "SetProtections"; }
+};
/// Write to a remote memory block.
- class WriteMem
- : public rpc::Function<WriteMem, void(remote::DirectBufferWriter DB)> {
- public:
- static const char *getName() { return "WriteMem"; }
- };
+class WriteMem
+ : public shared::RPCFunction<WriteMem,
+ void(remote::DirectBufferWriter DB)> {
+public:
+ static const char *getName() { return "WriteMem"; }
+};
/// Write to a remote pointer.
- class WritePtr : public rpc::Function<WritePtr, void(JITTargetAddress Dst,
- JITTargetAddress Val)> {
- public:
- static const char *getName() { return "WritePtr"; }
- };
+class WritePtr
+ : public shared::RPCFunction<WritePtr, void(JITTargetAddress Dst,
+ JITTargetAddress Val)> {
+public:
+ static const char *getName() { return "WritePtr"; }
+};
} // end namespace mem
@@ -280,45 +290,46 @@
namespace stubs {
/// Creates an indirect stub owner on the remote.
- class CreateIndirectStubsOwner
- : public rpc::Function<CreateIndirectStubsOwner,
- void(ResourceIdMgr::ResourceId StubOwnerID)> {
- public:
- static const char *getName() { return "CreateIndirectStubsOwner"; }
- };
+class CreateIndirectStubsOwner
+ : public shared::RPCFunction<CreateIndirectStubsOwner,
+ void(ResourceIdMgr::ResourceId StubOwnerID)> {
+public:
+ static const char *getName() { return "CreateIndirectStubsOwner"; }
+};
/// RPC function for destroying an indirect stubs owner.
- class DestroyIndirectStubsOwner
- : public rpc::Function<DestroyIndirectStubsOwner,
- void(ResourceIdMgr::ResourceId StubsOwnerID)> {
- public:
- static const char *getName() { return "DestroyIndirectStubsOwner"; }
- };
+class DestroyIndirectStubsOwner
+ : public shared::RPCFunction<DestroyIndirectStubsOwner,
+ void(ResourceIdMgr::ResourceId StubsOwnerID)> {
+public:
+ static const char *getName() { return "DestroyIndirectStubsOwner"; }
+};
/// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
- class EmitIndirectStubs
- : public rpc::Function<
- EmitIndirectStubs,
- std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>(
- ResourceIdMgr::ResourceId StubsOwnerID,
- uint32_t NumStubsRequired)> {
- public:
- static const char *getName() { return "EmitIndirectStubs"; }
- };
+class EmitIndirectStubs
+ : public shared::RPCFunction<
+ EmitIndirectStubs,
+ std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>(
+ ResourceIdMgr::ResourceId StubsOwnerID,
+ uint32_t NumStubsRequired)> {
+public:
+ static const char *getName() { return "EmitIndirectStubs"; }
+};
/// RPC function to emit the resolver block and return its address.
- class EmitResolverBlock : public rpc::Function<EmitResolverBlock, void()> {
- public:
- static const char *getName() { return "EmitResolverBlock"; }
- };
+class EmitResolverBlock
+ : public shared::RPCFunction<EmitResolverBlock, void()> {
+public:
+ static const char *getName() { return "EmitResolverBlock"; }
+};
/// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
- class EmitTrampolineBlock
- : public rpc::Function<EmitTrampolineBlock,
- std::tuple<JITTargetAddress, uint32_t>()> {
- public:
- static const char *getName() { return "EmitTrampolineBlock"; }
- };
+class EmitTrampolineBlock
+ : public shared::RPCFunction<EmitTrampolineBlock,
+ std::tuple<JITTargetAddress, uint32_t>()> {
+public:
+ static const char *getName() { return "EmitTrampolineBlock"; }
+};
} // end namespace stubs
@@ -327,44 +338,44 @@
/// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
/// IndirectStubsSize).
- class GetRemoteInfo
- : public rpc::Function<
- GetRemoteInfo,
- std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> {
- public:
- static const char *getName() { return "GetRemoteInfo"; }
- };
+class GetRemoteInfo
+ : public shared::RPCFunction<
+ GetRemoteInfo,
+ std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> {
+public:
+ static const char *getName() { return "GetRemoteInfo"; }
+};
/// Get the address of a remote symbol.
- class GetSymbolAddress
- : public rpc::Function<GetSymbolAddress,
- JITTargetAddress(std::string SymbolName)> {
- public:
- static const char *getName() { return "GetSymbolAddress"; }
- };
+class GetSymbolAddress
+ : public shared::RPCFunction<GetSymbolAddress,
+ JITTargetAddress(std::string SymbolName)> {
+public:
+ static const char *getName() { return "GetSymbolAddress"; }
+};
/// Request that the host execute a compile callback.
- class RequestCompile
- : public rpc::Function<
- RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> {
- public:
- static const char *getName() { return "RequestCompile"; }
- };
+class RequestCompile
+ : public shared::RPCFunction<
+ RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> {
+public:
+ static const char *getName() { return "RequestCompile"; }
+};
/// Notify the remote and terminate the session.
- class TerminateSession : public rpc::Function<TerminateSession, void()> {
- public:
- static const char *getName() { return "TerminateSession"; }
- };
+class TerminateSession : public shared::RPCFunction<TerminateSession, void()> {
+public:
+ static const char *getName() { return "TerminateSession"; }
+};
} // namespace utils
class OrcRemoteTargetRPCAPI
- : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
+ : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> {
public:
// FIXME: Remove constructors once MSVC supports synthesizing move-ops.
- OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
- : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {}
+ OrcRemoteTargetRPCAPI(shared::RawByteChannel &C)
+ : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(C, true) {}
};
} // end namespace remote
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index 4c8e2ea..68eccf4 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
#include "llvm/Support/Debug.h"
@@ -45,7 +46,7 @@
template <typename ChannelT, typename TargetT>
class OrcRemoteTargetServer
- : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
+ : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> {
public:
using SymbolLookupFtor =
std::function<JITTargetAddress(const std::string &Name)>;
@@ -56,12 +57,14 @@
OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
EHFrameRegistrationFtor EHFramesRegister,
EHFrameRegistrationFtor EHFramesDeregister)
- : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
+ : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(Channel,
+ true),
SymbolLookup(std::move(SymbolLookup)),
EHFramesRegister(std::move(EHFramesRegister)),
EHFramesDeregister(std::move(EHFramesDeregister)) {
- using ThisT = typename std::remove_reference<decltype(*this)>::type;
+ using ThisT = std::remove_reference_t<decltype(*this)>;
addHandler<exec::CallIntVoid>(*this, &ThisT::handleCallIntVoid);
+ addHandler<exec::CallIntInt>(*this, &ThisT::handleCallIntInt);
addHandler<exec::CallMain>(*this, &ThisT::handleCallMain);
addHandler<exec::CallVoidVoid>(*this, &ThisT::handleCallVoidVoid);
addHandler<mem::CreateRemoteAllocator>(*this,
@@ -167,6 +170,19 @@
return Result;
}
+ Expected<int32_t> handleCallIntInt(JITTargetAddress Addr, int Arg) {
+ using IntIntFnTy = int (*)(int);
+
+ IntIntFnTy Fn = reinterpret_cast<IntIntFnTy>(static_cast<uintptr_t>(Addr));
+
+ LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr)
+ << " with argument " << Arg << "\n");
+ int Result = Fn(Arg);
+ LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
+
+ return Result;
+ }
+
Expected<int32_t> handleCallMain(JITTargetAddress Addr,
std::vector<std::string> Args) {
using MainFnTy = int (*)(int, const char *[]);
@@ -262,19 +278,17 @@
return errorCodeToError(
orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist));
- typename TargetT::IndirectStubsInfo IS;
- if (auto Err =
- TargetT::emitIndirectStubsBlock(IS, NumStubsRequired, nullptr))
- return std::move(Err);
+ auto IS = LocalIndirectStubsInfo<TargetT>::create(
+ NumStubsRequired, sys::Process::getPageSizeEstimate());
+ if (!IS)
+ return IS.takeError();
- JITTargetAddress StubsBase = static_cast<JITTargetAddress>(
- reinterpret_cast<uintptr_t>(IS.getStub(0)));
- JITTargetAddress PtrsBase = static_cast<JITTargetAddress>(
- reinterpret_cast<uintptr_t>(IS.getPtr(0)));
- uint32_t NumStubsEmitted = IS.getNumStubs();
+ JITTargetAddress StubsBase = pointerToJITTargetAddress(IS->getStub(0));
+ JITTargetAddress PtrsBase = pointerToJITTargetAddress(IS->getPtr(0));
+ uint32_t NumStubsEmitted = IS->getNumStubs();
auto &BlockList = StubOwnerItr->second;
- BlockList.push_back(std::move(IS));
+ BlockList.push_back(std::move(*IS));
return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
}
@@ -287,8 +301,10 @@
if (EC)
return errorCodeToError(EC);
- TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
- &reenter, this);
+ TargetT::writeResolverCode(static_cast<char *>(ResolverBlock.base()),
+ pointerToJITTargetAddress(ResolverBlock.base()),
+ pointerToJITTargetAddress(&reenter),
+ pointerToJITTargetAddress(this));
return errorCodeToError(sys::Memory::protectMappedMemory(
ResolverBlock.getMemoryBlock(),
@@ -308,9 +324,10 @@
(sys::Process::getPageSizeEstimate() - TargetT::PointerSize) /
TargetT::TrampolineSize;
- uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
- TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
- NumTrampolines);
+ char *TrampolineMem = static_cast<char *>(TrampolineBlock.base());
+ TargetT::writeTrampolines(
+ TrampolineMem, pointerToJITTargetAddress(TrampolineMem),
+ pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines);
EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(),
sys::Memory::MF_READ |
@@ -318,10 +335,8 @@
TrampolineBlocks.push_back(std::move(TrampolineBlock));
- auto TrampolineBaseAddr = static_cast<JITTargetAddress>(
- reinterpret_cast<uintptr_t>(TrampolineMem));
-
- return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
+ return std::make_tuple(pointerToJITTargetAddress(TrampolineMem),
+ NumTrampolines);
}
Expected<JITTargetAddress> handleGetSymbolAddress(const std::string &Name) {
@@ -337,7 +352,7 @@
uint32_t PointerSize = TargetT::PointerSize;
uint32_t PageSize = sys::Process::getPageSizeEstimate();
uint32_t TrampolineSize = TargetT::TrampolineSize;
- uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
+ uint32_t IndirectStubSize = TargetT::StubSize;
LLVM_DEBUG(dbgs() << " Remote info:\n"
<< " triple = '" << ProcessTriple << "'\n"
<< " pointer size = " << PointerSize << "\n"
@@ -433,7 +448,7 @@
SymbolLookupFtor SymbolLookup;
EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister;
std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
- using ISBlockOwnerList = std::vector<typename TargetT::IndirectStubsInfo>;
+ using ISBlockOwnerList = std::vector<LocalIndirectStubsInfo<TargetT>>;
std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;
sys::OwningMemoryBlock ResolverBlock;
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 479658b..7dfbf32 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -16,10 +16,10 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/JITEventListener.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"
#include "llvm/Support/Error.h"
@@ -35,16 +35,16 @@
namespace llvm {
namespace orc {
-class RTDyldObjectLinkingLayer : public ObjectLayer {
+class RTDyldObjectLinkingLayer : public ObjectLayer, private ResourceManager {
public:
/// Functor for receiving object-loaded notifications.
- using NotifyLoadedFunction =
- std::function<void(VModuleKey, const object::ObjectFile &Obj,
- const RuntimeDyld::LoadedObjectInfo &)>;
+ using NotifyLoadedFunction = std::function<void(
+ MaterializationResponsibility &R, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving finalization notifications.
- using NotifyEmittedFunction =
- std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>;
+ using NotifyEmittedFunction = std::function<void(
+ MaterializationResponsibility &R, std::unique_ptr<MemoryBuffer>)>;
using GetMemoryManagerFunction =
std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
@@ -54,8 +54,10 @@
RTDyldObjectLinkingLayer(ExecutionSession &ES,
GetMemoryManagerFunction GetMemoryManager);
+ ~RTDyldObjectLinkingLayer();
+
/// Emit the object.
- void emit(MaterializationResponsibility R,
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) override;
/// Set the NotifyLoaded callback.
@@ -113,15 +115,30 @@
return *this;
}
+ /// Register a JITEventListener.
+ void registerJITEventListener(JITEventListener &L);
+
+ /// Unregister a JITEventListener.
+ void unregisterJITEventListener(JITEventListener &L);
+
private:
- Error onObjLoad(VModuleKey K, MaterializationResponsibility &R,
- object::ObjectFile &Obj,
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
+ using MemoryManagerUP = std::unique_ptr<RuntimeDyld::MemoryManager>;
+
+ Error onObjLoad(MaterializationResponsibility &R,
+ const object::ObjectFile &Obj,
+ RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> Resolved,
std::set<StringRef> &InternalSymbols);
- void onObjEmit(VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
- MaterializationResponsibility &R, Error Err);
+ void onObjEmit(MaterializationResponsibility &R,
+ object::OwningBinary<object::ObjectFile> O,
+ std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
+ Error Err);
+
+ Error handleRemoveResources(ResourceKey K) override;
+ void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
mutable std::mutex RTDyldLayerMutex;
GetMemoryManagerFunction GetMemoryManager;
@@ -130,340 +147,8 @@
bool ProcessAllSections = false;
bool OverrideObjectFlags = false;
bool AutoClaimObjectSymbols = false;
- std::vector<std::unique_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
-};
-
-class LegacyRTDyldObjectLinkingLayerBase {
-public:
- using ObjectPtr = std::unique_ptr<MemoryBuffer>;
-
-protected:
-
- /// 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
- /// removeObject) frees its memory, removing all symbol definitions that
- /// had been provided by this instance. Higher level layers are responsible
- /// for taking any action required to handle the missing symbols.
- class LinkedObject {
- public:
- LinkedObject() = default;
- LinkedObject(const LinkedObject&) = delete;
- void operator=(const LinkedObject&) = delete;
- virtual ~LinkedObject() = default;
-
- virtual Error finalize() = 0;
-
- virtual JITSymbol::GetAddressFtor
- getSymbolMaterializer(std::string Name) = 0;
-
- virtual void mapSectionAddress(const void *LocalAddress,
- JITTargetAddress TargetAddr) const = 0;
-
- JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
- auto SymEntry = SymbolTable.find(Name);
- if (SymEntry == SymbolTable.end())
- return nullptr;
- if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
- return nullptr;
- if (!Finalized)
- return JITSymbol(getSymbolMaterializer(Name),
- SymEntry->second.getFlags());
- return JITSymbol(SymEntry->second);
- }
-
- protected:
- StringMap<JITEvaluatedSymbol> SymbolTable;
- bool Finalized = false;
- };
-};
-
-/// 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
-/// symbols queried. All objects added to this layer can see each other's
-/// symbols.
-class LegacyRTDyldObjectLinkingLayer : public LegacyRTDyldObjectLinkingLayerBase {
-public:
-
- using LegacyRTDyldObjectLinkingLayerBase::ObjectPtr;
-
- /// Functor for receiving object-loaded notifications.
- using NotifyLoadedFtor =
- std::function<void(VModuleKey, const object::ObjectFile &Obj,
- const RuntimeDyld::LoadedObjectInfo &)>;
-
- /// 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>;
-
- template <typename MemoryManagerPtrT>
- class ConcreteLinkedObject : public LinkedObject {
- public:
- ConcreteLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
- OwnedObject Obj, MemoryManagerPtrT MemMgr,
- std::shared_ptr<SymbolResolver> Resolver,
- bool ProcessAllSections)
- : K(std::move(K)),
- Parent(Parent),
- MemMgr(std::move(MemMgr)),
- PFC(llvm::make_unique<PreFinalizeContents>(
- std::move(Obj), std::move(Resolver),
- ProcessAllSections)) {
- buildInitialSymbolTable(PFC->Obj);
- }
-
- ~ConcreteLinkedObject() override {
- if (this->Parent.NotifyFreed && ObjForNotify.getBinary())
- this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
-
- MemMgr->deregisterEHFrames();
- }
-
- Error finalize() override {
- assert(PFC && "mapSectionAddress called on finalized LinkedObject");
-
- JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
- nullptr);
- PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
- PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
-
- Finalized = true;
-
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
- PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
-
- // Copy the symbol table out of the RuntimeDyld instance.
- {
- auto SymTab = PFC->RTDyld->getSymbolTable();
- for (auto &KV : SymTab)
- SymbolTable[KV.first] = KV.second;
- }
-
- if (Parent.NotifyLoaded)
- Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
-
- PFC->RTDyld->finalizeWithMemoryManagerLocking();
-
- if (PFC->RTDyld->hasError())
- return make_error<StringError>(PFC->RTDyld->getErrorString(),
- inconvertibleErrorCode());
-
- 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();
- }
-
- JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
- return [this, Name]() -> Expected<JITTargetAddress> {
- // The symbol may be materialized between the creation of this lambda
- // and its execution, so we need to double check.
- if (!this->Finalized)
- if (auto Err = this->finalize())
- return std::move(Err);
- return this->getSymbol(Name, false).getAddress();
- };
- }
-
- void mapSectionAddress(const void *LocalAddress,
- JITTargetAddress TargetAddr) const override {
- assert(PFC && "mapSectionAddress called on finalized LinkedObject");
- assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
- PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
- }
-
- private:
- void buildInitialSymbolTable(const OwnedObject &Obj) {
- for (auto &Symbol : Obj.getBinary()->symbols()) {
- if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
- continue;
- Expected<StringRef> SymbolName = Symbol.getName();
- // FIXME: Raise an error for bad symbols.
- if (!SymbolName) {
- 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)));
- }
- }
-
- // Contains the information needed prior to finalization: the object files,
- // memory manager, resolver, and flags needed for RuntimeDyld.
- struct PreFinalizeContents {
- PreFinalizeContents(OwnedObject Obj,
- std::shared_ptr<SymbolResolver> Resolver,
- bool ProcessAllSections)
- : Obj(std::move(Obj)),
- Resolver(std::move(Resolver)),
- ProcessAllSections(ProcessAllSections) {}
-
- OwnedObject Obj;
- std::shared_ptr<SymbolResolver> Resolver;
- bool ProcessAllSections;
- std::unique_ptr<RuntimeDyld> RTDyld;
- };
-
- VModuleKey K;
- LegacyRTDyldObjectLinkingLayer &Parent;
- MemoryManagerPtrT MemMgr;
- OwnedObject ObjForNotify;
- std::unique_ptr<PreFinalizeContents> PFC;
- };
-
- template <typename MemoryManagerPtrT>
- std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
- createLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
- OwnedObject Obj, MemoryManagerPtrT MemMgr,
- std::shared_ptr<SymbolResolver> Resolver,
- bool ProcessAllSections) {
- using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
- return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
- std::move(MemMgr), std::move(Resolver),
- ProcessAllSections);
- }
-
-public:
- struct Resources {
- std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
- std::shared_ptr<SymbolResolver> Resolver;
- };
-
- using ResourcesGetter = std::function<Resources(VModuleKey)>;
-
- /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
- /// and NotifyFinalized functors.
- LegacyRTDyldObjectLinkingLayer(
- ExecutionSession &ES, ResourcesGetter GetResources,
- NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
- NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
- NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
- : ES(ES), GetResources(std::move(GetResources)),
- NotifyLoaded(std::move(NotifyLoaded)),
- NotifyFinalized(std::move(NotifyFinalized)),
- NotifyFreed(std::move(NotifyFreed)),
- ProcessAllSections(false) {
- }
-
- /// 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;
- }
-
- /// Add an object to the JIT.
- Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
-
- auto Obj =
- object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
- if (!Obj)
- return Obj.takeError();
-
- assert(!LinkedObjects.count(K) && "VModuleKey already in use");
-
- auto R = GetResources(K);
-
- LinkedObjects[K] = createLinkedObject(
- *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
- std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
-
- return Error::success();
- }
-
- /// 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
- /// re-emit the missing symbols, and any use of these symbols (directly or
- /// indirectly) will result in undefined behavior. If dependence tracking is
- /// required to detect or resolve such issues it should be added at a higher
- /// layer.
- Error removeObject(VModuleKey K) {
- assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
- // How do we invalidate the symbols in H?
- LinkedObjects.erase(K);
- return Error::success();
- }
-
- /// 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.
- JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
- for (auto &KV : LinkedObjects)
- if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
-
- return nullptr;
- }
-
- /// 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.
- /// @param ExportedSymbolsOnly If true, search only for exported symbols.
- /// @return A handle for the given named symbol, if it is found in the
- /// given object.
- JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
- bool ExportedSymbolsOnly) {
- assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
- return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
- }
-
- /// Map section addresses for the object associated with the
- /// VModuleKey K.
- void mapSectionAddress(VModuleKey K, const void *LocalAddress,
- JITTargetAddress TargetAddr) {
- assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
- LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
- }
-
- /// Immediately emit and finalize the object represented by the given
- /// VModuleKey.
- /// @param K VModuleKey for object to emit/finalize.
- Error emitAndFinalize(VModuleKey K) {
- assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
- return LinkedObjects[K]->finalize();
- }
-
-private:
- ExecutionSession &ES;
-
- ResourcesGetter GetResources;
- NotifyLoadedFtor NotifyLoaded;
- NotifyFinalizedFtor NotifyFinalized;
- NotifyFreedFtor NotifyFreed;
-
- // NB! `LinkedObjects` needs to be destroyed before `NotifyFreed` because
- // `~ConcreteLinkedObject` calls `NotifyFreed`
- std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
- bool ProcessAllSections = false;
+ DenseMap<ResourceKey, std::vector<MemoryManagerUP>> MemMgrs;
+ std::vector<JITEventListener *> EventListeners;
};
} // end namespace orc
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
deleted file mode 100644
index 9550edc..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
+++ /dev/null
@@ -1,528 +0,0 @@
-//===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Forwards objects to a remote object layer via RPC.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
-#define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
-
-#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
-#include <map>
-
-namespace llvm {
-namespace orc {
-
-/// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.
-class RemoteObjectLayerAPI {
-public:
-
- using ObjHandleT = remote::ResourceIdMgr::ResourceId;
-
-protected:
-
- using RemoteSymbolId = remote::ResourceIdMgr::ResourceId;
- using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;
-
-public:
-
- using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>;
- using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>;
-
-protected:
-
- static const ObjHandleT InvalidObjectHandleId = 0;
- static const RemoteSymbolId NullSymbolId = 0;
-
- class AddObject
- : public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> {
- public:
- static const char *getName() { return "AddObject"; }
- };
-
- class RemoveObject
- : public rpc::Function<RemoveObject, Error(ObjHandleT)> {
- public:
- static const char *getName() { return "RemoveObject"; }
- };
-
- class FindSymbol
- : public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string,
- bool)> {
- public:
- static const char *getName() { return "FindSymbol"; }
- };
-
- class FindSymbolIn
- : public rpc::Function<FindSymbolIn,
- Expected<RemoteSymbol>(ObjHandleT, std::string,
- bool)> {
- public:
- static const char *getName() { return "FindSymbolIn"; }
- };
-
- class EmitAndFinalize
- : public rpc::Function<EmitAndFinalize,
- Error(ObjHandleT)> {
- public:
- static const char *getName() { return "EmitAndFinalize"; }
- };
-
- class Lookup
- : public rpc::Function<Lookup,
- Expected<RemoteSymbol>(ObjHandleT, std::string)> {
- public:
- static const char *getName() { return "Lookup"; }
- };
-
- class LookupInLogicalDylib
- : public rpc::Function<LookupInLogicalDylib,
- Expected<RemoteSymbol>(ObjHandleT, std::string)> {
- public:
- static const char *getName() { return "LookupInLogicalDylib"; }
- };
-
- class ReleaseRemoteSymbol
- : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
- public:
- static const char *getName() { return "ReleaseRemoteSymbol"; }
- };
-
- class MaterializeRemoteSymbol
- : public rpc::Function<MaterializeRemoteSymbol,
- Expected<JITTargetAddress>(RemoteSymbolId)> {
- public:
- static const char *getName() { return "MaterializeRemoteSymbol"; }
- };
-};
-
-/// Base class containing common utilities for RemoteObjectClientLayer and
-/// RemoteObjectServerLayer.
-template <typename RPCEndpoint>
-class RemoteObjectLayer : public RemoteObjectLayerAPI {
-public:
-
- RemoteObjectLayer(RPCEndpoint &Remote,
- std::function<void(Error)> ReportError)
- : Remote(Remote), ReportError(std::move(ReportError)),
- SymbolIdMgr(NullSymbolId + 1) {
- using ThisT = RemoteObjectLayer<RPCEndpoint>;
- Remote.template addHandler<ReleaseRemoteSymbol>(
- *this, &ThisT::handleReleaseRemoteSymbol);
- Remote.template addHandler<MaterializeRemoteSymbol>(
- *this, &ThisT::handleMaterializeRemoteSymbol);
- }
-
-protected:
-
- /// This class is used as the symbol materializer for JITSymbols returned by
- /// RemoteObjectLayerClient/RemoteObjectLayerServer -- the materializer knows
- /// how to call back to the other RPC endpoint to get the address when
- /// requested.
- class RemoteSymbolMaterializer {
- public:
-
- /// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer
- /// with the given Id.
- RemoteSymbolMaterializer(RemoteObjectLayer &C,
- RemoteSymbolId Id)
- : C(C), Id(Id) {}
-
- RemoteSymbolMaterializer(const RemoteSymbolMaterializer &Other)
- : C(Other.C), Id(Other.Id) {
- // FIXME: This is a horrible, auto_ptr-style, copy-as-move operation.
- // It should be removed as soon as LLVM has C++14's generalized
- // lambda capture (at which point the materializer can be moved
- // into the lambda in remoteToJITSymbol below).
- const_cast<RemoteSymbolMaterializer&>(Other).Id = 0;
- }
-
- RemoteSymbolMaterializer&
- operator=(const RemoteSymbolMaterializer&) = delete;
-
- /// Release the remote symbol.
- ~RemoteSymbolMaterializer() {
- if (Id)
- C.releaseRemoteSymbol(Id);
- }
-
- /// Materialize the symbol on the remote and get its address.
- Expected<JITTargetAddress> materialize() {
- auto Addr = C.materializeRemoteSymbol(Id);
- Id = 0;
- return Addr;
- }
-
- private:
- RemoteObjectLayer &C;
- RemoteSymbolId Id;
- };
-
- /// Convenience function for getting a null remote symbol value.
- RemoteSymbol nullRemoteSymbol() {
- return RemoteSymbol(0, JITSymbolFlags());
- }
-
- /// Creates a StringError that contains a copy of Err's log message, then
- /// sends that StringError to ReportError.
- ///
- /// This allows us to locally log error messages for errors that will actually
- /// be delivered to the remote.
- Error teeLog(Error Err) {
- return handleErrors(std::move(Err),
- [this](std::unique_ptr<ErrorInfoBase> EIB) {
- ReportError(make_error<StringError>(
- EIB->message(),
- EIB->convertToErrorCode()));
- return Error(std::move(EIB));
- });
- }
-
- Error badRemoteSymbolIdError(RemoteSymbolId Id) {
- return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
- }
-
- Error badObjectHandleError(ObjHandleT H) {
- return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
- H, "Bad object handle");
- }
-
- /// Create a RemoteSymbol wrapping the given JITSymbol.
- Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {
- if (Sym) {
- auto Id = SymbolIdMgr.getNext();
- auto Flags = Sym.getFlags();
- assert(!InUseSymbols.count(Id) && "Symbol id already in use");
- InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));
- return RemoteSymbol(Id, Flags);
- } else if (auto Err = Sym.takeError())
- return teeLog(std::move(Err));
- // else...
- return nullRemoteSymbol();
- }
-
- /// Convert an Expected<RemoteSymbol> to a JITSymbol.
- JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {
- if (RemoteSymOrErr) {
- auto &RemoteSym = *RemoteSymOrErr;
- if (RemoteSym == nullRemoteSymbol())
- return nullptr;
- // else...
- RemoteSymbolMaterializer RSM(*this, RemoteSym.first);
- auto Sym =
- JITSymbol([RSM]() mutable { return RSM.materialize(); },
- RemoteSym.second);
- return Sym;
- } else
- return RemoteSymOrErr.takeError();
- }
-
- RPCEndpoint &Remote;
- std::function<void(Error)> ReportError;
-
-private:
-
- /// Notify the remote to release the given JITSymbol.
- void releaseRemoteSymbol(RemoteSymbolId Id) {
- if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))
- ReportError(std::move(Err));
- }
-
- /// Notify the remote to materialize the JITSymbol with the given Id and
- /// return its address.
- Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
- return Remote.template callB<MaterializeRemoteSymbol>(Id);
- }
-
- /// Release the JITSymbol with the given Id.
- Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {
- auto SI = InUseSymbols.find(Id);
- if (SI != InUseSymbols.end()) {
- InUseSymbols.erase(SI);
- return Error::success();
- } else
- return teeLog(badRemoteSymbolIdError(Id));
- }
-
- /// Run the materializer for the JITSymbol with the given Id and return its
- /// address.
- Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {
- auto SI = InUseSymbols.find(Id);
- if (SI != InUseSymbols.end()) {
- auto AddrOrErr = SI->second.getAddress();
- InUseSymbols.erase(SI);
- SymbolIdMgr.release(Id);
- if (AddrOrErr)
- return *AddrOrErr;
- else
- return teeLog(AddrOrErr.takeError());
- } else {
- return teeLog(badRemoteSymbolIdError(Id));
- }
- }
-
- remote::ResourceIdMgr SymbolIdMgr;
- std::map<RemoteSymbolId, JITSymbol> InUseSymbols;
-};
-
-/// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC
-/// connection.
-///
-/// This class can be used as the base layer of a JIT stack on the client and
-/// will forward operations to a corresponding RemoteObjectServerLayer on the
-/// server (which can be composed on top of a "real" object layer like
-/// RTDyldObjectLinkingLayer to actually carry out the operations).
-///
-/// Sending relocatable objects to the server (rather than fully relocated
-/// bits) allows JIT'd code to be cached on the server side and re-used in
-/// subsequent JIT sessions.
-template <typename RPCEndpoint>
-class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {
-private:
-
- using AddObject = RemoteObjectLayerAPI::AddObject;
- using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
- using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
- using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
- using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
- using Lookup = RemoteObjectLayerAPI::Lookup;
- using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
-
- using RemoteObjectLayer<RPCEndpoint>::teeLog;
- using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
- using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
-
-public:
-
- using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
- using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
-
- using ObjectPtr = std::unique_ptr<MemoryBuffer>;
-
- /// Create a RemoteObjectClientLayer that communicates with a
- /// RemoteObjectServerLayer instance via the given RPCEndpoint.
- ///
- /// The ReportError functor can be used locally log errors that are intended
- /// to be sent sent
- RemoteObjectClientLayer(RPCEndpoint &Remote,
- std::function<void(Error)> ReportError)
- : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
- using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
- Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
- Remote.template addHandler<LookupInLogicalDylib>(
- *this, &ThisT::lookupInLogicalDylib);
- }
-
- /// 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.).
- Expected<ObjHandleT>
- addObject(ObjectPtr ObjBuffer,
- std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
- if (auto HandleOrErr =
- this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) {
- auto &Handle = *HandleOrErr;
- // FIXME: Return an error for this:
- assert(!Resolvers.count(Handle) && "Handle already in use?");
- Resolvers[Handle] = std::move(Resolver);
- return Handle;
- } else
- return HandleOrErr.takeError();
- }
-
- /// Remove the given object from the JIT.
- Error removeObject(ObjHandleT H) {
- return this->Remote.template callB<RemoveObject>(H);
- }
-
- /// Search for the given named symbol.
- JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
- return remoteToJITSymbol(
- this->Remote.template callB<FindSymbol>(Name,
- ExportedSymbolsOnly));
- }
-
- /// 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));
- }
-
- /// Immediately emit and finalize the object with the given handle.
- Error emitAndFinalize(ObjHandleT H) {
- return this->Remote.template callB<EmitAndFinalize>(H);
- }
-
-private:
-
- Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {
- auto RI = Resolvers.find(H);
- if (RI != Resolvers.end()) {
- return this->jitSymbolToRemote(RI->second->findSymbol(Name));
- } else
- return teeLog(badObjectHandleError(H));
- }
-
- Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,
- const std::string &Name) {
- auto RI = Resolvers.find(H);
- if (RI != Resolvers.end())
- return this->jitSymbolToRemote(
- RI->second->findSymbolInLogicalDylib(Name));
- else
- return teeLog(badObjectHandleError(H));
- }
-
- std::map<remote::ResourceIdMgr::ResourceId,
- std::shared_ptr<LegacyJITSymbolResolver>>
- Resolvers;
-};
-
-/// RemoteObjectServerLayer acts as a server and handling RPC calls for the
-/// object layer API from the given RPC connection.
-///
-/// This class can be composed on top of a 'real' object layer (e.g.
-/// RTDyldObjectLinkingLayer) to do the actual work of relocating objects
-/// and making them executable.
-template <typename BaseLayerT, typename RPCEndpoint>
-class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {
-private:
-
- using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
- using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
-
- using AddObject = RemoteObjectLayerAPI::AddObject;
- using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
- using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
- using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
- using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
- using Lookup = RemoteObjectLayerAPI::Lookup;
- using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
-
- using RemoteObjectLayer<RPCEndpoint>::teeLog;
- using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
- using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
-
-public:
-
- /// Create a RemoteObjectServerLayer with the given base layer (which must be
- /// an object layer), RPC endpoint, and error reporter function.
- RemoteObjectServerLayer(BaseLayerT &BaseLayer,
- RPCEndpoint &Remote,
- std::function<void(Error)> ReportError)
- : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
- BaseLayer(BaseLayer), HandleIdMgr(1) {
- using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
-
- Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
- Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
- Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
- Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
- Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
- }
-
-private:
-
- class StringMemoryBuffer : public MemoryBuffer {
- public:
- StringMemoryBuffer(std::string Buffer)
- : Buffer(std::move(Buffer)) {
- init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
- false);
- }
-
- BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
- private:
- std::string Buffer;
- };
-
- JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
- return remoteToJITSymbol(
- this->Remote.template callB<Lookup>(Id, Name));
- }
-
- JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
- return remoteToJITSymbol(
- this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
- }
-
- Expected<ObjHandleT> addObject(std::string ObjBuffer) {
- auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
- auto Id = HandleIdMgr.getNext();
- assert(!BaseLayerHandles.count(Id) && "Id already in use?");
-
- auto Resolver = createLambdaResolver(
- [this, Id](const std::string &Name) { return lookup(Id, Name); },
- [this, Id](const std::string &Name) {
- return lookupInLogicalDylib(Id, Name);
- });
-
- if (auto HandleOrErr =
- BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) {
- BaseLayerHandles[Id] = std::move(*HandleOrErr);
- return Id;
- } else
- return teeLog(HandleOrErr.takeError());
- }
-
- Error removeObject(ObjHandleT H) {
- auto HI = BaseLayerHandles.find(H);
- if (HI != BaseLayerHandles.end()) {
- if (auto Err = BaseLayer.removeObject(HI->second))
- return teeLog(std::move(Err));
- return Error::success();
- } else
- return teeLog(badObjectHandleError(H));
- }
-
- Expected<RemoteSymbol> findSymbol(const std::string &Name,
- bool ExportedSymbolsOnly) {
- if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
- return this->jitSymbolToRemote(std::move(Sym));
- else if (auto Err = Sym.takeError())
- return teeLog(std::move(Err));
- return this->nullRemoteSymbol();
- }
-
- Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,
- bool ExportedSymbolsOnly) {
- auto HI = BaseLayerHandles.find(H);
- if (HI != BaseLayerHandles.end()) {
- if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))
- return this->jitSymbolToRemote(std::move(Sym));
- else if (auto Err = Sym.takeError())
- return teeLog(std::move(Err));
- return this->nullRemoteSymbol();
- } else
- return teeLog(badObjectHandleError(H));
- }
-
- Error emitAndFinalize(ObjHandleT H) {
- auto HI = BaseLayerHandles.find(H);
- if (HI != BaseLayerHandles.end()) {
- if (auto Err = BaseLayer.emitAndFinalize(HI->second))
- return teeLog(std::move(Err));
- return Error::success();
- } else
- return teeLog(badObjectHandleError(H));
- }
-
- BaseLayerT &BaseLayer;
- remote::ResourceIdMgr HandleIdMgr;
- std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;
-};
-
-} // end namespace orc
-} // end namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h
new file mode 100644
index 0000000..3f96fe3
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h
@@ -0,0 +1,79 @@
+//===- FDRawByteChannel.h - File descriptor based byte-channel -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// File descriptor based RawByteChannel.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_FDRAWBYTECHANNEL_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_FDRAWBYTECHANNEL_H
+
+#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+namespace llvm {
+namespace orc {
+namespace shared {
+
+/// Serialization channel that reads from and writes from file descriptors.
+class FDRawByteChannel final : public RawByteChannel {
+public:
+ FDRawByteChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
+
+ llvm::Error readBytes(char *Dst, unsigned Size) override {
+ assert(Dst && "Attempt to read into null.");
+ ssize_t Completed = 0;
+ while (Completed < static_cast<ssize_t>(Size)) {
+ ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);
+ if (Read <= 0) {
+ auto ErrNo = errno;
+ if (ErrNo == EAGAIN || ErrNo == EINTR)
+ continue;
+ else
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
+ }
+ Completed += Read;
+ }
+ return llvm::Error::success();
+ }
+
+ llvm::Error appendBytes(const char *Src, unsigned Size) override {
+ assert(Src && "Attempt to append from null.");
+ ssize_t Completed = 0;
+ while (Completed < static_cast<ssize_t>(Size)) {
+ ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed);
+ if (Written < 0) {
+ auto ErrNo = errno;
+ if (ErrNo == EAGAIN || ErrNo == EINTR)
+ continue;
+ else
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
+ }
+ Completed += Written;
+ }
+ return llvm::Error::success();
+ }
+
+ llvm::Error send() override { return llvm::Error::success(); }
+
+private:
+ int InFD, OutFD;
+};
+
+} // namespace shared
+} // namespace orc
+} // namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_FDRAWBYTECHANNEL_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/RPCUtils.h
similarity index 85%
rename from linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
rename to linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/RPCUtils.h
index 3b11e1b..1c8b8e0 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/RPCUtils.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
-#define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_RPCUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_RPCUTILS_H
#include <map>
#include <thread>
@@ -23,14 +23,14 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
-#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
+#include "llvm/ExecutionEngine/Orc/Shared/Serialization.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
#include <future>
namespace llvm {
namespace orc {
-namespace rpc {
+namespace shared {
/// Base class of all fatal RPC errors (those that necessarily result in the
/// termination of the RPC session).
@@ -56,7 +56,7 @@
/// function id it cannot parse the call.
template <typename FnIdT, typename SeqNoT>
class BadFunctionCall
- : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
+ : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
public:
static char ID;
@@ -68,8 +68,10 @@
}
void log(raw_ostream &OS) const override {
- OS << "Call to invalid RPC function id '" << FnId << "' with "
- "sequence number " << SeqNo;
+ OS << "Call to invalid RPC function id '" << FnId
+ << "' with "
+ "sequence number "
+ << SeqNo;
}
private:
@@ -89,12 +91,12 @@
/// a result parser for this sequence number it can't do that.
template <typename SeqNoT>
class InvalidSequenceNumberForResponse
- : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
+ : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>,
+ RPCFatalError> {
public:
static char ID;
- InvalidSequenceNumberForResponse(SeqNoT SeqNo)
- : SeqNo(std::move(SeqNo)) {}
+ InvalidSequenceNumberForResponse(SeqNoT SeqNo) : SeqNo(std::move(SeqNo)) {}
std::error_code convertToErrorCode() const override {
return orcError(OrcErrorCode::UnexpectedRPCCall);
@@ -103,6 +105,7 @@
void log(raw_ostream &OS) const override {
OS << "Response has unknown sequence number " << SeqNo;
}
+
private:
SeqNoT SeqNo;
};
@@ -131,17 +134,18 @@
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
const std::string &getSignature() const { return Signature; }
+
private:
std::string Signature;
};
-template <typename DerivedFunc, typename FnT> class Function;
+template <typename DerivedFunc, typename FnT> class RPCFunction;
// RPC Function class.
// DerivedFunc should be a user defined class with a static 'getName()' method
// returning a const char* representing the function's name.
template <typename DerivedFunc, typename RetT, typename... ArgTs>
-class Function<DerivedFunc, RetT(ArgTs...)> {
+class RPCFunction<DerivedFunc, RetT(ArgTs...)> {
public:
/// User defined function type.
using Type = RetT(ArgTs...);
@@ -154,8 +158,9 @@
static std::string Name = [] {
std::string Name;
raw_string_ostream(Name)
- << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName()
- << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")";
+ << SerializationTypeName<RetT>::getName() << " "
+ << DerivedFunc::getName() << "("
+ << SerializationTypeNameSequence<ArgTs...>() << ")";
return Name;
}();
return Name.data();
@@ -184,8 +189,7 @@
/// This specialization of RPCFunctionIdAllocator provides a default
/// implementation for integral types.
template <typename T>
-class RPCFunctionIdAllocator<
- T, typename std::enable_if<std::is_integral<T>::value>::type> {
+class RPCFunctionIdAllocator<T, std::enable_if_t<std::is_integral<T>::value>> {
public:
static T getInvalidId() { return T(0); }
static T getResponseId() { return T(1); }
@@ -200,13 +204,12 @@
namespace detail {
/// Provides a typedef for a tuple containing the decayed argument types.
-template <typename T> class FunctionArgsTuple;
+template <typename T> class RPCFunctionArgsTuple;
template <typename RetT, typename... ArgTs>
-class FunctionArgsTuple<RetT(ArgTs...)> {
+class RPCFunctionArgsTuple<RetT(ArgTs...)> {
public:
- using Type = std::tuple<typename std::decay<
- typename std::remove_reference<ArgTs>::type>::type...>;
+ using Type = std::tuple<std::decay_t<std::remove_reference_t<ArgTs>>...>;
};
// ResultTraits provides typedefs and utilities specific to the return type
@@ -289,34 +292,28 @@
// Determines whether an RPC function's defined error return type supports
// error return value.
-template <typename T>
-class SupportsErrorReturn {
+template <typename T> class SupportsErrorReturn {
public:
static const bool value = false;
};
-template <>
-class SupportsErrorReturn<Error> {
+template <> class SupportsErrorReturn<Error> {
public:
static const bool value = true;
};
-template <typename T>
-class SupportsErrorReturn<Expected<T>> {
+template <typename T> class SupportsErrorReturn<Expected<T>> {
public:
static const bool value = true;
};
// RespondHelper packages return values based on whether or not the declared
// RPC function return type supports error returns.
-template <bool FuncSupportsErrorReturn>
-class RespondHelper;
+template <bool FuncSupportsErrorReturn> class RespondHelper;
// RespondHelper specialization for functions that support error returns.
-template <>
-class RespondHelper<true> {
+template <> class RespondHelper<true> {
public:
-
// Send Expected<T>.
template <typename WireRetT, typename HandlerRetT, typename ChannelT,
typename FunctionIdT, typename SequenceNumberT>
@@ -332,13 +329,14 @@
// Serialize the result.
if (auto Err =
- SerializationTraits<ChannelT, WireRetT,
- Expected<HandlerRetT>>::serialize(
- C, std::move(ResultOrErr)))
+ SerializationTraits<ChannelT, WireRetT, Expected<HandlerRetT>>::
+ serialize(C, std::move(ResultOrErr)))
return Err;
// Close the response message.
- return C.endSendMessage();
+ if (auto Err = C.endSendMessage())
+ return Err;
+ return C.send();
}
template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
@@ -350,16 +348,15 @@
return Err2;
if (auto Err2 = serializeSeq(C, std::move(Err)))
return Err2;
- return C.endSendMessage();
+ if (auto Err2 = C.endSendMessage())
+ return Err2;
+ return C.send();
}
-
};
// RespondHelper specialization for functions that do not support error returns.
-template <>
-class RespondHelper<false> {
+template <> class RespondHelper<false> {
public:
-
template <typename WireRetT, typename HandlerRetT, typename ChannelT,
typename FunctionIdT, typename SequenceNumberT>
static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
@@ -374,12 +371,15 @@
// Serialize the result.
if (auto Err =
- SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize(
- C, *ResultOrErr))
+ SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize(
+ C, *ResultOrErr))
return Err;
- // Close the response message.
- return C.endSendMessage();
+ // End the response message.
+ if (auto Err = C.endSendMessage())
+ return Err;
+
+ return C.send();
}
template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
@@ -389,20 +389,21 @@
return Err;
if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
return Err2;
- return C.endSendMessage();
+ if (auto Err2 = C.endSendMessage())
+ return Err2;
+ return C.send();
}
-
};
-
// Send a response of the given wire return type (WireRetT) over the
// channel, with the given sequence number.
template <typename WireRetT, typename HandlerRetT, typename ChannelT,
typename FunctionIdT, typename SequenceNumberT>
-Error respond(ChannelT &C, const FunctionIdT &ResponseId,
- SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) {
+Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo,
+ Expected<HandlerRetT> ResultOrErr) {
return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
- template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr));
+ template sendResult<WireRetT>(C, ResponseId, SeqNo,
+ std::move(ResultOrErr));
}
// Send an empty response message on the given channel to indicate that
@@ -411,8 +412,8 @@
typename SequenceNumberT>
Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo,
Error Err) {
- return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
- sendResult(C, ResponseId, SeqNo, std::move(Err));
+ return RespondHelper<SupportsErrorReturn<WireRetT>::value>::sendResult(
+ C, ResponseId, SeqNo, std::move(Err));
}
// Converts a given type to the equivalent error return type.
@@ -446,7 +447,8 @@
template <typename FnT> class AsyncHandlerTraits;
template <typename ResultT, typename... ArgTs>
-class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> {
+class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>,
+ ArgTs...)> {
public:
using Type = Error(ArgTs...);
using ResultType = Expected<ResultT>;
@@ -474,18 +476,18 @@
};
template <typename ResponseHandlerT, typename... ArgTs>
-class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> :
- public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type,
- ArgTs...)> {};
+class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)>
+ : public AsyncHandlerTraits<Error(std::decay_t<ResponseHandlerT>,
+ ArgTs...)> {};
// This template class provides utilities related to RPC function handlers.
// The base case applies to non-function types (the template class is
// specialized for function types) and inherits from the appropriate
// speciilization for the given non-function type's call operator.
template <typename HandlerT>
-class HandlerTraits : public HandlerTraits<decltype(
- &std::remove_reference<HandlerT>::type::operator())> {
-};
+class HandlerTraits
+ : public HandlerTraits<
+ decltype(&std::remove_reference<HandlerT>::type::operator())> {};
// Traits for handlers with a given function type.
template <typename RetT, typename... ArgTs>
@@ -502,7 +504,7 @@
static typename WrappedHandlerReturn<RetT>::Type
unpackAndRun(HandlerT &Handler, std::tuple<TArgTs...> &Args) {
return unpackAndRunHelper(Handler, Args,
- llvm::index_sequence_for<TArgTs...>());
+ std::index_sequence_for<TArgTs...>());
}
// Call the given handler with the given arguments.
@@ -510,23 +512,22 @@
static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder,
std::tuple<TArgTs...> &Args) {
return unpackAndRunAsyncHelper(Handler, Responder, Args,
- llvm::index_sequence_for<TArgTs...>());
+ std::index_sequence_for<TArgTs...>());
}
// Call the given handler with the given arguments.
template <typename HandlerT>
- static typename std::enable_if<
- std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
- Error>::type
- run(HandlerT &Handler, ArgTs &&... Args) {
+ static std::enable_if_t<
+ std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value, Error>
+ run(HandlerT &Handler, ArgTs &&...Args) {
Handler(std::move(Args)...);
return Error::success();
}
template <typename HandlerT, typename... TArgTs>
- static typename std::enable_if<
+ static std::enable_if_t<
!std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
- typename HandlerTraits<HandlerT>::ReturnType>::type
+ typename HandlerTraits<HandlerT>::ReturnType>
run(HandlerT &Handler, TArgTs... Args) {
return Handler(std::move(Args)...);
}
@@ -540,14 +541,13 @@
// Deserialize arguments from the channel.
template <typename ChannelT, typename... CArgTs>
static Error deserializeArgs(ChannelT &C, std::tuple<CArgTs...> &Args) {
- return deserializeArgsHelper(C, Args,
- llvm::index_sequence_for<CArgTs...>());
+ return deserializeArgsHelper(C, Args, std::index_sequence_for<CArgTs...>());
}
private:
template <typename ChannelT, typename... CArgTs, size_t... Indexes>
static Error deserializeArgsHelper(ChannelT &C, std::tuple<CArgTs...> &Args,
- llvm::index_sequence<Indexes...> _) {
+ std::index_sequence<Indexes...> _) {
return SequenceSerialization<ChannelT, ArgTs...>::deserialize(
C, std::get<Indexes>(Args)...);
}
@@ -556,26 +556,24 @@
static typename WrappedHandlerReturn<
typename HandlerTraits<HandlerT>::ReturnType>::Type
unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args,
- llvm::index_sequence<Indexes...>) {
+ std::index_sequence<Indexes...>) {
return run(Handler, std::move(std::get<Indexes>(Args))...);
}
-
template <typename HandlerT, typename ResponderT, typename ArgTuple,
size_t... Indexes>
static typename WrappedHandlerReturn<
typename HandlerTraits<HandlerT>::ReturnType>::Type
unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder,
- ArgTuple &Args,
- llvm::index_sequence<Indexes...>) {
+ ArgTuple &Args, std::index_sequence<Indexes...>) {
return run(Handler, Responder, std::move(std::get<Indexes>(Args))...);
}
};
// Handler traits for free functions.
template <typename RetT, typename... ArgTs>
-class HandlerTraits<RetT(*)(ArgTs...)>
- : public HandlerTraits<RetT(ArgTs...)> {};
+class HandlerTraits<RetT (*)(ArgTs...)> : public HandlerTraits<RetT(ArgTs...)> {
+};
// Handler traits for class methods (especially call operators for lambdas).
template <typename Class, typename RetT, typename... ArgTs>
@@ -711,9 +709,8 @@
typename HandlerTraits<HandlerT>::Type>::ArgType;
HandlerArgType Result((typename HandlerArgType::value_type()));
- if (auto Err =
- SerializationTraits<ChannelT, Expected<FuncRetT>,
- HandlerArgType>::deserialize(C, Result))
+ if (auto Err = SerializationTraits<ChannelT, Expected<FuncRetT>,
+ HandlerArgType>::deserialize(C, Result))
return Err;
if (auto Err = C.endReceiveMessage())
return Err;
@@ -743,11 +740,15 @@
// to the user defined handler.
Error handleResponse(ChannelT &C) override {
Error Result = Error::success();
- if (auto Err =
- SerializationTraits<ChannelT, Error, Error>::deserialize(C, Result))
+ if (auto Err = SerializationTraits<ChannelT, Error, Error>::deserialize(
+ C, Result)) {
+ consumeError(std::move(Result));
return Err;
- if (auto Err = C.endReceiveMessage())
+ }
+ if (auto Err = C.endReceiveMessage()) {
+ consumeError(std::move(Result));
return Err;
+ }
return Handler(std::move(Result));
}
@@ -767,7 +768,7 @@
// Create a ResponseHandler from a given user handler.
template <typename ChannelT, typename FuncRetT, typename HandlerT>
std::unique_ptr<ResponseHandler<ChannelT>> createResponseHandler(HandlerT H) {
- return llvm::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>(
+ return std::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>(
std::move(H));
}
@@ -779,7 +780,7 @@
using MethodT = RetT (ClassT::*)(ArgTs...);
MemberFnWrapper(ClassT &Instance, MethodT Method)
: Instance(Instance), Method(Method) {}
- RetT operator()(ArgTs &&... Args) {
+ RetT operator()(ArgTs &&...Args) {
return (Instance.*Method)(std::move(Args)...);
}
@@ -797,10 +798,9 @@
template <typename ArgT, typename... ArgTs>
class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {
public:
- ReadArgs(ArgT &Arg, ArgTs &... Args)
- : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
+ ReadArgs(ArgT &Arg, ArgTs &...Args) : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
- Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
+ Error operator()(ArgT &ArgVal, ArgTs &...ArgVals) {
this->Arg = std::move(ArgVal);
return ReadArgs<ArgTs...>::operator()(ArgVals...);
}
@@ -865,8 +865,8 @@
template <template <class, class> class P, typename T1Sig, typename T2Sig>
class RPCArgTypeCheck {
public:
- using T1Tuple = typename FunctionArgsTuple<T1Sig>::Type;
- using T2Tuple = typename FunctionArgsTuple<T2Sig>::Type;
+ using T1Tuple = typename RPCFunctionArgsTuple<T1Sig>::Type;
+ using T2Tuple = typename RPCFunctionArgsTuple<T2Sig>::Type;
static_assert(std::tuple_size<T1Tuple>::value >=
std::tuple_size<T2Tuple>::value,
@@ -884,12 +884,12 @@
using S = SerializationTraits<ChannelT, WireT, ConcreteT>;
template <typename T>
- static std::true_type
- check(typename std::enable_if<
- std::is_same<decltype(T::serialize(std::declval<ChannelT &>(),
- std::declval<const ConcreteT &>())),
- Error>::value,
- void *>::type);
+ static std::true_type check(
+ std::enable_if_t<std::is_same<decltype(T::serialize(
+ std::declval<ChannelT &>(),
+ std::declval<const ConcreteT &>())),
+ Error>::value,
+ void *>);
template <typename> static std::false_type check(...);
@@ -904,11 +904,11 @@
template <typename T>
static std::true_type
- check(typename std::enable_if<
- std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(),
- std::declval<ConcreteT &>())),
- Error>::value,
- void *>::type);
+ check(std::enable_if_t<
+ std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(),
+ std::declval<ConcreteT &>())),
+ Error>::value,
+ void *>);
template <typename> static std::false_type check(...);
@@ -930,18 +930,18 @@
typename SequenceNumberT>
class RPCEndpointBase {
protected:
- class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> {
+ class OrcRPCInvalid : public RPCFunction<OrcRPCInvalid, void()> {
public:
static const char *getName() { return "__orc_rpc$invalid"; }
};
- class OrcRPCResponse : public Function<OrcRPCResponse, void()> {
+ class OrcRPCResponse : public RPCFunction<OrcRPCResponse, void()> {
public:
static const char *getName() { return "__orc_rpc$response"; }
};
class OrcRPCNegotiate
- : public Function<OrcRPCNegotiate, FunctionIdT(std::string)> {
+ : public RPCFunction<OrcRPCNegotiate, FunctionIdT(std::string)> {
public:
static const char *getName() { return "__orc_rpc$negotiate"; }
};
@@ -987,7 +987,6 @@
[this](const std::string &Name) { return handleNegotiate(Name); });
}
-
/// Negotiate a function id for Func with the other end of the channel.
template <typename Func> Error negotiateFunction(bool Retry = false) {
return getRemoteFunctionId<Func>(true, Retry).takeError();
@@ -999,7 +998,7 @@
/// or an Error (if Func::ReturnType is void). The handler will be called
/// with an error if the return value is abandoned due to a channel error.
template <typename Func, typename HandlerT, typename... ArgTs>
- Error appendCallAsync(HandlerT Handler, const ArgTs &... Args) {
+ Error appendCallAsync(HandlerT Handler, const ArgTs &...Args) {
static_assert(
detail::RPCArgTypeCheck<CanSerializeCheck, typename Func::Type,
@@ -1029,8 +1028,8 @@
// Install the user handler.
PendingResponses[SeqNo] =
- detail::createResponseHandler<ChannelT, typename Func::ReturnType>(
- std::move(Handler));
+ detail::createResponseHandler<ChannelT, typename Func::ReturnType>(
+ std::move(Handler));
}
// Open the function call message.
@@ -1058,7 +1057,7 @@
Error sendAppendedCalls() { return C.send(); };
template <typename Func, typename HandlerT, typename... ArgTs>
- Error callAsync(HandlerT Handler, const ArgTs &... Args) {
+ Error callAsync(HandlerT Handler, const ArgTs &...Args) {
if (auto Err = appendCallAsync<Func>(std::move(Handler), Args...))
return Err;
return C.send();
@@ -1097,7 +1096,7 @@
/// /* Handle Args */ ;
///
template <typename... ArgTs>
- static detail::ReadArgs<ArgTs...> readArgs(ArgTs &... Args) {
+ static detail::ReadArgs<ArgTs...> readArgs(ArgTs &...Args) {
return detail::ReadArgs<ArgTs...>(Args...);
}
@@ -1121,8 +1120,7 @@
/// Remove the handler for the given function.
/// A handler must currently be registered for this function.
- template <typename Func>
- void removeHandler() {
+ template <typename Func> void removeHandler() {
auto IdItr = LocalFunctionIds.find(Func::getPrototype());
assert(IdItr != LocalFunctionIds.end() &&
"Function does not have a registered handler");
@@ -1133,12 +1131,9 @@
}
/// Clear all handlers.
- void clearHandlers() {
- Handlers.clear();
- }
+ void clearHandlers() { Handlers.clear(); }
protected:
-
FunctionIdT getInvalidFunctionId() const {
return FnIdAllocator.getInvalidId();
}
@@ -1161,12 +1156,12 @@
template <typename Func, typename HandlerT>
void addAsyncHandlerImpl(HandlerT Handler) {
- static_assert(detail::RPCArgTypeCheck<
- CanDeserializeCheck, typename Func::Type,
- typename detail::AsyncHandlerTraits<
- typename detail::HandlerTraits<HandlerT>::Type
- >::Type>::value,
- "");
+ static_assert(
+ detail::RPCArgTypeCheck<
+ CanDeserializeCheck, typename Func::Type,
+ typename detail::AsyncHandlerTraits<
+ typename detail::HandlerTraits<HandlerT>::Type>::Type>::value,
+ "");
FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
LocalFunctionIds[Func::getPrototype()] = NewFnId;
@@ -1190,8 +1185,8 @@
// Unlock the pending results map to prevent recursive lock.
Lock.unlock();
abandonPendingResponses();
- return make_error<
- InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo);
+ return make_error<InvalidSequenceNumberForResponse<SequenceNumberT>>(
+ SeqNo);
}
}
@@ -1234,7 +1229,7 @@
if (DoNegotiate) {
auto &Impl = static_cast<ImplT &>(*this);
if (auto RemoteIdOrErr =
- Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
+ Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
if (*RemoteIdOrErr == getInvalidFunctionId())
return make_error<CouldNotNegotiate>(Func::getPrototype());
@@ -1257,9 +1252,8 @@
return [this, Handler](ChannelT &Channel,
SequenceNumberT SeqNo) mutable -> Error {
// Start by deserializing the arguments.
- using ArgsTuple =
- typename detail::FunctionArgsTuple<
- typename detail::HandlerTraits<HandlerT>::Type>::Type;
+ using ArgsTuple = typename detail::RPCFunctionArgsTuple<
+ typename detail::HandlerTraits<HandlerT>::Type>::Type;
auto Args = std::make_shared<ArgsTuple>();
if (auto Err =
@@ -1291,9 +1285,9 @@
SequenceNumberT SeqNo) mutable -> Error {
// Start by deserializing the arguments.
using AHTraits = detail::AsyncHandlerTraits<
- typename detail::HandlerTraits<HandlerT>::Type>;
+ typename detail::HandlerTraits<HandlerT>::Type>;
using ArgsTuple =
- typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type;
+ typename detail::RPCFunctionArgsTuple<typename AHTraits::Type>::Type;
auto Args = std::make_shared<ArgsTuple>();
if (auto Err =
@@ -1312,11 +1306,11 @@
using HTraits = detail::HandlerTraits<HandlerT>;
using FuncReturn = typename Func::ReturnType;
- auto Responder =
- [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error {
- return detail::respond<FuncReturn>(C, ResponseId, SeqNo,
- std::move(RetVal));
- };
+ auto Responder = [this,
+ SeqNo](typename AHTraits::ResultType RetVal) -> Error {
+ return detail::respond<FuncReturn>(C, ResponseId, SeqNo,
+ std::move(RetVal));
+ };
return HTraits::unpackAndRunAsync(Handler, Responder, *Args);
};
@@ -1349,17 +1343,16 @@
MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
ChannelT, FunctionIdT, SequenceNumberT> {
private:
- using BaseClass =
- detail::RPCEndpointBase<
- MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
- ChannelT, FunctionIdT, SequenceNumberT>;
+ using BaseClass = detail::RPCEndpointBase<
+ MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
+ ChannelT, FunctionIdT, SequenceNumberT>;
public:
MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
: BaseClass(C, LazyAutoNegotiation) {}
/// Add a handler for the given RPC function.
- /// This installs the given handler functor for the given RPC Function, and
+ /// This installs the given handler functor for the given RPCFunction, and
/// makes the RPC function available for negotiation/calling from the remote.
template <typename Func, typename HandlerT>
void addHandler(HandlerT Handler) {
@@ -1370,7 +1363,7 @@
template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
addHandler<Func>(
- detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
template <typename Func, typename HandlerT>
@@ -1382,7 +1375,7 @@
template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
addAsyncHandler<Func>(
- detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
/// Return type for non-blocking call primitives.
@@ -1398,19 +1391,17 @@
/// result. In multi-threaded mode the appendCallNB method, which does not
/// return the sequence numeber, should be preferred.
template <typename Func, typename... ArgTs>
- Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &... Args) {
+ Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &...Args) {
using RTraits = detail::ResultTraits<typename Func::ReturnType>;
using ErrorReturn = typename RTraits::ErrorReturnType;
using ErrorReturnPromise = typename RTraits::ReturnPromiseType;
- // FIXME: Stack allocate and move this into the handler once LLVM builds
- // with C++14.
- auto Promise = std::make_shared<ErrorReturnPromise>();
- auto FutureResult = Promise->get_future();
+ ErrorReturnPromise Promise;
+ auto FutureResult = Promise.get_future();
if (auto Err = this->template appendCallAsync<Func>(
- [Promise](ErrorReturn RetOrErr) {
- Promise->set_value(std::move(RetOrErr));
+ [Promise = std::move(Promise)](ErrorReturn RetOrErr) mutable {
+ Promise.set_value(std::move(RetOrErr));
return Error::success();
},
Args...)) {
@@ -1423,7 +1414,7 @@
/// The same as appendCallNBWithSeq, except that it calls C.send() to
/// flush the channel after serializing the call.
template <typename Func, typename... ArgTs>
- Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &... Args) {
+ Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &...Args) {
auto Result = appendCallNB<Func>(Args...);
if (!Result)
return Result;
@@ -1444,7 +1435,7 @@
template <typename Func, typename... ArgTs,
typename AltRetT = typename Func::ReturnType>
typename detail::ResultTraits<AltRetT>::ErrorReturnType
- callB(const ArgTs &... Args) {
+ callB(const ArgTs &...Args) {
if (auto FutureResOrErr = callNB<Func>(Args...))
return FutureResOrErr->get();
else
@@ -1467,10 +1458,9 @@
SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
ChannelT, FunctionIdT, SequenceNumberT> {
private:
- using BaseClass =
- detail::RPCEndpointBase<
- SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
- ChannelT, FunctionIdT, SequenceNumberT>;
+ using BaseClass = detail::RPCEndpointBase<
+ SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
+ ChannelT, FunctionIdT, SequenceNumberT>;
public:
SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
@@ -1496,13 +1486,13 @@
template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
addAsyncHandler<Func>(
- detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
template <typename Func, typename... ArgTs,
typename AltRetT = typename Func::ReturnType>
typename detail::ResultTraits<AltRetT>::ErrorReturnType
- callB(const ArgTs &... Args) {
+ callB(const ArgTs &...Args) {
bool ReceivedResponse = false;
using ResultType = typename detail::ResultTraits<AltRetT>::ErrorReturnType;
auto Result = detail::ResultTraits<AltRetT>::createBlankErrorReturnValue();
@@ -1523,6 +1513,12 @@
return std::move(Err);
}
+ if (auto Err = this->C.send()) {
+ detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
+ std::move(Result));
+ return std::move(Err);
+ }
+
while (!ReceivedResponse) {
if (auto Err = this->handleOne()) {
detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
@@ -1536,13 +1532,12 @@
};
/// Asynchronous dispatch for a function on an RPC endpoint.
-template <typename RPCClass, typename Func>
-class RPCAsyncDispatch {
+template <typename RPCClass, typename Func> class RPCAsyncDispatch {
public:
RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {}
template <typename HandlerT, typename... ArgTs>
- Error operator()(HandlerT Handler, const ArgTs &... Args) const {
+ Error operator()(HandlerT Handler, const ArgTs &...Args) const {
return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...);
}
@@ -1560,7 +1555,6 @@
/// waited on as a group.
class ParallelCallGroup {
public:
-
ParallelCallGroup() = default;
ParallelCallGroup(const ParallelCallGroup &) = delete;
ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
@@ -1568,7 +1562,7 @@
/// Make as asynchronous call.
template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
- const ArgTs &... Args) {
+ const ArgTs &...Args) {
// Increment the count of outstanding calls. This has to happen before
// we invoke the call, as the handler may (depending on scheduling)
// be run immediately on another thread, and we don't want the decrement
@@ -1582,8 +1576,7 @@
// outstanding calls count, then poke the condition variable.
using ArgType = typename detail::ResponseHandlerArg<
typename detail::HandlerTraits<HandlerT>::Type>::ArgType;
- // FIXME: Move handler into wrapped handler once we have C++14.
- auto WrappedHandler = [this, Handler](ArgType Arg) {
+ auto WrappedHandler = [this, Handler = std::move(Handler)](ArgType Arg) {
auto Err = Handler(std::move(Arg));
std::unique_lock<std::mutex> Lock(M);
--NumOutstandingCalls;
@@ -1608,70 +1601,57 @@
uint32_t NumOutstandingCalls = 0;
};
-/// Convenience class for grouping RPC Functions into APIs that can be
+/// Convenience class for grouping RPCFunctions into APIs that can be
/// negotiated as a block.
///
-template <typename... Funcs>
-class APICalls {
+template <typename... Funcs> class APICalls {
public:
-
/// Test whether this API contains Function F.
- template <typename F>
- class Contains {
+ template <typename F> class Contains {
public:
static const bool value = false;
};
/// Negotiate all functions in this API.
- template <typename RPCEndpoint>
- static Error negotiate(RPCEndpoint &R) {
+ template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) {
return Error::success();
}
};
-template <typename Func, typename... Funcs>
-class APICalls<Func, Funcs...> {
+template <typename Func, typename... Funcs> class APICalls<Func, Funcs...> {
public:
-
- template <typename F>
- class Contains {
+ template <typename F> class Contains {
public:
static const bool value = std::is_same<F, Func>::value |
APICalls<Funcs...>::template Contains<F>::value;
};
- template <typename RPCEndpoint>
- static Error negotiate(RPCEndpoint &R) {
+ template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) {
if (auto Err = R.template negotiateFunction<Func>())
return Err;
return APICalls<Funcs...>::negotiate(R);
}
-
};
template <typename... InnerFuncs, typename... Funcs>
class APICalls<APICalls<InnerFuncs...>, Funcs...> {
public:
-
- template <typename F>
- class Contains {
+ template <typename F> class Contains {
public:
static const bool value =
- APICalls<InnerFuncs...>::template Contains<F>::value |
- APICalls<Funcs...>::template Contains<F>::value;
+ APICalls<InnerFuncs...>::template Contains<F>::value |
+ APICalls<Funcs...>::template Contains<F>::value;
};
- template <typename RPCEndpoint>
- static Error negotiate(RPCEndpoint &R) {
+ template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) {
if (auto Err = APICalls<InnerFuncs...>::negotiate(R))
return Err;
return APICalls<Funcs...>::negotiate(R);
}
-
};
-} // end namespace rpc
+} // end namespace shared
} // end namespace orc
} // end namespace llvm
-#endif
+#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_RPCUTILS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RawByteChannel.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h
similarity index 74%
rename from linux-x64/clang/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
rename to linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h
index 46b7c59..2ee4719 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h
@@ -1,4 +1,4 @@
-//===- llvm/ExecutionEngine/Orc/RawByteChannel.h ----------------*- C++ -*-===//
+//===- RawByteChannel.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
-#define LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_RAWBYTECHANNEL_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_RAWBYTECHANNEL_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
+#include "llvm/ExecutionEngine/Orc/Shared/Serialization.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -20,9 +20,9 @@
namespace llvm {
namespace orc {
-namespace rpc {
+namespace shared {
-/// Interface for byte-streams to be used with RPC.
+/// Interface for byte-streams to be used with ORC Serialization.
class RawByteChannel {
public:
virtual ~RawByteChannel() = default;
@@ -87,13 +87,13 @@
template <typename ChannelT, typename T>
class SerializationTraits<
ChannelT, T, T,
- typename std::enable_if<
+ std::enable_if_t<
std::is_base_of<RawByteChannel, ChannelT>::value &&
(std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value ||
std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
- std::is_same<T, char>::value)>::type> {
+ std::is_same<T, char>::value)>> {
public:
static Error serialize(ChannelT &C, T V) {
support::endian::byte_swap<T, support::big>(V);
@@ -109,14 +109,13 @@
};
template <typename ChannelT>
-class SerializationTraits<ChannelT, bool, bool,
- typename std::enable_if<std::is_base_of<
- RawByteChannel, ChannelT>::value>::type> {
+class SerializationTraits<
+ ChannelT, bool, bool,
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
public:
static Error serialize(ChannelT &C, bool V) {
uint8_t Tmp = V ? 1 : 0;
- if (auto Err =
- C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1))
+ if (auto Err = C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1))
return Err;
return Error::success();
}
@@ -131,11 +130,11 @@
};
template <typename ChannelT>
-class SerializationTraits<ChannelT, std::string, StringRef,
- typename std::enable_if<std::is_base_of<
- RawByteChannel, ChannelT>::value>::type> {
+class SerializationTraits<
+ ChannelT, std::string, StringRef,
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
public:
- /// RPC channel serialization for std::strings.
+ /// Serialization channel serialization for std::strings.
static Error serialize(RawByteChannel &C, StringRef S) {
if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
return Err;
@@ -144,11 +143,11 @@
};
template <typename ChannelT, typename T>
-class SerializationTraits<ChannelT, std::string, T,
- typename std::enable_if<
- std::is_base_of<RawByteChannel, ChannelT>::value &&
- (std::is_same<T, const char*>::value ||
- std::is_same<T, char*>::value)>::type> {
+class SerializationTraits<
+ ChannelT, std::string, T,
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value &&
+ (std::is_same<T, const char *>::value ||
+ std::is_same<T, char *>::value)>> {
public:
static Error serialize(RawByteChannel &C, const char *S) {
return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
@@ -157,17 +156,17 @@
};
template <typename ChannelT>
-class SerializationTraits<ChannelT, std::string, std::string,
- typename std::enable_if<std::is_base_of<
- RawByteChannel, ChannelT>::value>::type> {
+class SerializationTraits<
+ ChannelT, std::string, std::string,
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
public:
- /// RPC channel serialization for std::strings.
+ /// Serialization channel serialization for std::strings.
static Error serialize(RawByteChannel &C, const std::string &S) {
return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
S);
}
- /// RPC channel deserialization for std::strings.
+ /// Serialization channel deserialization for std::strings.
static Error deserialize(RawByteChannel &C, std::string &S) {
uint64_t Count = 0;
if (auto Err = deserializeSeq(C, Count))
@@ -177,8 +176,8 @@
}
};
-} // end namespace rpc
+} // end namespace shared
} // end namespace orc
} // end namespace llvm
-#endif // LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
+#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_RAWBYTECHANNEL_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/Serialization.h
similarity index 61%
rename from linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
rename to linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/Serialization.h
index 07c7471..64a4ab8 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/Serialization.h
@@ -1,4 +1,4 @@
-//===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===//
+//===- Serialization.h ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,10 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
-#define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SERIALIZATION_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_SERIALIZATION_H
-#include "OrcError.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/Support/thread.h"
#include <map>
#include <mutex>
@@ -20,118 +22,104 @@
namespace llvm {
namespace orc {
-namespace rpc {
+namespace shared {
-template <typename T>
-class RPCTypeName;
+template <typename T> class SerializationTypeName;
/// TypeNameSequence is a utility for rendering sequences of types to a string
/// by rendering each type, separated by ", ".
-template <typename... ArgTs> class RPCTypeNameSequence {};
+template <typename... ArgTs> class SerializationTypeNameSequence {};
/// Render an empty TypeNameSequence to an ostream.
template <typename OStream>
-OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
+OStream &operator<<(OStream &OS, const SerializationTypeNameSequence<> &V) {
return OS;
}
/// Render a TypeNameSequence of a single type to an ostream.
template <typename OStream, typename ArgT>
-OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
- OS << RPCTypeName<ArgT>::getName();
+OStream &operator<<(OStream &OS, const SerializationTypeNameSequence<ArgT> &V) {
+ OS << SerializationTypeName<ArgT>::getName();
return OS;
}
/// Render a TypeNameSequence of more than one type to an ostream.
template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
-OStream&
-operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
- OS << RPCTypeName<ArgT1>::getName() << ", "
- << RPCTypeNameSequence<ArgT2, ArgTs...>();
+OStream &
+operator<<(OStream &OS,
+ const SerializationTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
+ OS << SerializationTypeName<ArgT1>::getName() << ", "
+ << SerializationTypeNameSequence<ArgT2, ArgTs...>();
return OS;
}
-template <>
-class RPCTypeName<void> {
+template <> class SerializationTypeName<void> {
public:
- static const char* getName() { return "void"; }
+ static const char *getName() { return "void"; }
};
-template <>
-class RPCTypeName<int8_t> {
+template <> class SerializationTypeName<int8_t> {
public:
- static const char* getName() { return "int8_t"; }
+ static const char *getName() { return "int8_t"; }
};
-template <>
-class RPCTypeName<uint8_t> {
+template <> class SerializationTypeName<uint8_t> {
public:
- static const char* getName() { return "uint8_t"; }
+ static const char *getName() { return "uint8_t"; }
};
-template <>
-class RPCTypeName<int16_t> {
+template <> class SerializationTypeName<int16_t> {
public:
- static const char* getName() { return "int16_t"; }
+ static const char *getName() { return "int16_t"; }
};
-template <>
-class RPCTypeName<uint16_t> {
+template <> class SerializationTypeName<uint16_t> {
public:
- static const char* getName() { return "uint16_t"; }
+ static const char *getName() { return "uint16_t"; }
};
-template <>
-class RPCTypeName<int32_t> {
+template <> class SerializationTypeName<int32_t> {
public:
- static const char* getName() { return "int32_t"; }
+ static const char *getName() { return "int32_t"; }
};
-template <>
-class RPCTypeName<uint32_t> {
+template <> class SerializationTypeName<uint32_t> {
public:
- static const char* getName() { return "uint32_t"; }
+ static const char *getName() { return "uint32_t"; }
};
-template <>
-class RPCTypeName<int64_t> {
+template <> class SerializationTypeName<int64_t> {
public:
- static const char* getName() { return "int64_t"; }
+ static const char *getName() { return "int64_t"; }
};
-template <>
-class RPCTypeName<uint64_t> {
+template <> class SerializationTypeName<uint64_t> {
public:
- static const char* getName() { return "uint64_t"; }
+ static const char *getName() { return "uint64_t"; }
};
-template <>
-class RPCTypeName<bool> {
+template <> class SerializationTypeName<bool> {
public:
- static const char* getName() { return "bool"; }
+ static const char *getName() { return "bool"; }
};
-template <>
-class RPCTypeName<std::string> {
+template <> class SerializationTypeName<std::string> {
public:
- static const char* getName() { return "std::string"; }
+ static const char *getName() { return "std::string"; }
};
-template <>
-class RPCTypeName<Error> {
+template <> class SerializationTypeName<Error> {
public:
- static const char* getName() { return "Error"; }
+ static const char *getName() { return "Error"; }
};
-template <typename T>
-class RPCTypeName<Expected<T>> {
+template <typename T> class SerializationTypeName<Expected<T>> {
public:
- static const char* getName() {
+ static const char *getName() {
static std::string Name = [] {
std::string Name;
- raw_string_ostream(Name) << "Expected<"
- << RPCTypeNameSequence<T>()
- << ">";
+ raw_string_ostream(Name)
+ << "Expected<" << SerializationTypeNameSequence<T>() << ">";
return Name;
}();
return Name.data();
@@ -139,67 +127,78 @@
};
template <typename T1, typename T2>
-class RPCTypeName<std::pair<T1, T2>> {
-public:
- static const char* getName() {
- static std::string Name = [] {
- std::string Name;
- raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
- << ">";
- return Name;
- }();
- return Name.data();
- }
-};
-
-template <typename... ArgTs>
-class RPCTypeName<std::tuple<ArgTs...>> {
-public:
- static const char* getName() {
- static std::string Name = [] {
- std::string Name;
- raw_string_ostream(Name) << "std::tuple<"
- << RPCTypeNameSequence<ArgTs...>() << ">";
- return Name;
- }();
- return Name.data();
- }
-};
-
-template <typename T>
-class RPCTypeName<std::vector<T>> {
-public:
- static const char*getName() {
- static std::string Name = [] {
- std::string Name;
- raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
- << ">";
- return Name;
- }();
- return Name.data();
- }
-};
-
-template <typename T> class RPCTypeName<std::set<T>> {
+class SerializationTypeName<std::pair<T1, T2>> {
public:
static const char *getName() {
static std::string Name = [] {
std::string Name;
raw_string_ostream(Name)
- << "std::set<" << RPCTypeName<T>::getName() << ">";
+ << "std::pair<" << SerializationTypeNameSequence<T1, T2>() << ">";
return Name;
}();
return Name.data();
}
};
-template <typename K, typename V> class RPCTypeName<std::map<K, V>> {
+template <typename... ArgTs> class SerializationTypeName<std::tuple<ArgTs...>> {
public:
static const char *getName() {
static std::string Name = [] {
std::string Name;
raw_string_ostream(Name)
- << "std::map<" << RPCTypeNameSequence<K, V>() << ">";
+ << "std::tuple<" << SerializationTypeNameSequence<ArgTs...>() << ">";
+ return Name;
+ }();
+ return Name.data();
+ }
+};
+
+template <typename T> class SerializationTypeName<Optional<T>> {
+public:
+ static const char *getName() {
+ static std::string Name = [] {
+ std::string Name;
+ raw_string_ostream(Name)
+ << "Optional<" << SerializationTypeName<T>::getName() << ">";
+ return Name;
+ }();
+ return Name.data();
+ }
+};
+
+template <typename T> class SerializationTypeName<std::vector<T>> {
+public:
+ static const char *getName() {
+ static std::string Name = [] {
+ std::string Name;
+ raw_string_ostream(Name)
+ << "std::vector<" << SerializationTypeName<T>::getName() << ">";
+ return Name;
+ }();
+ return Name.data();
+ }
+};
+
+template <typename T> class SerializationTypeName<std::set<T>> {
+public:
+ static const char *getName() {
+ static std::string Name = [] {
+ std::string Name;
+ raw_string_ostream(Name)
+ << "std::set<" << SerializationTypeName<T>::getName() << ">";
+ return Name;
+ }();
+ return Name.data();
+ }
+};
+
+template <typename K, typename V> class SerializationTypeName<std::map<K, V>> {
+public:
+ static const char *getName() {
+ static std::string Name = [] {
+ std::string Name;
+ raw_string_ostream(Name)
+ << "std::map<" << SerializationTypeNameSequence<K, V>() << ">";
return Name;
}();
return Name.data();
@@ -230,9 +229,9 @@
///
/// template <DerivedChannelT>
/// class SerializationTraits<DerivedChannelT, bool,
-/// typename std::enable_if<
+/// std::enable_if_t<
/// std::is_base_of<VirtChannel, DerivedChannel>::value
-/// >::type> {
+/// >> {
/// public:
/// static const char* getName() { ... };
/// }
@@ -242,8 +241,7 @@
typename ConcreteType = WireType, typename = void>
class SerializationTraits;
-template <typename ChannelT>
-class SequenceTraits {
+template <typename ChannelT> class SequenceTraits {
public:
static Error emitSeparator(ChannelT &C) { return Error::success(); }
static Error consumeSeparator(ChannelT &C) { return Error::success(); }
@@ -258,11 +256,9 @@
/// is a SerializationTraits specialization
/// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
/// caller argument to over-the-wire value.
-template <typename ChannelT, typename... ArgTs>
-class SequenceSerialization;
+template <typename ChannelT, typename... ArgTs> class SequenceSerialization;
-template <typename ChannelT>
-class SequenceSerialization<ChannelT> {
+template <typename ChannelT> class SequenceSerialization<ChannelT> {
public:
static Error serialize(ChannelT &C) { return Error::success(); }
static Error deserialize(ChannelT &C) { return Error::success(); }
@@ -271,16 +267,12 @@
template <typename ChannelT, typename ArgT>
class SequenceSerialization<ChannelT, ArgT> {
public:
-
- template <typename CArgT>
- static Error serialize(ChannelT &C, CArgT &&CArg) {
- return SerializationTraits<ChannelT, ArgT,
- typename std::decay<CArgT>::type>::
- serialize(C, std::forward<CArgT>(CArg));
+ template <typename CArgT> static Error serialize(ChannelT &C, CArgT &&CArg) {
+ return SerializationTraits<ChannelT, ArgT, std::decay_t<CArgT>>::serialize(
+ C, std::forward<CArgT>(CArg));
}
- template <typename CArgT>
- static Error deserialize(ChannelT &C, CArgT &CArg) {
+ template <typename CArgT> static Error deserialize(ChannelT &C, CArgT &CArg) {
return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
}
};
@@ -288,25 +280,22 @@
template <typename ChannelT, typename ArgT, typename... ArgTs>
class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
public:
-
template <typename CArgT, typename... CArgTs>
- static Error serialize(ChannelT &C, CArgT &&CArg,
- CArgTs &&... CArgs) {
+ static Error serialize(ChannelT &C, CArgT &&CArg, CArgTs &&...CArgs) {
if (auto Err =
- SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>::
- serialize(C, std::forward<CArgT>(CArg)))
+ SerializationTraits<ChannelT, ArgT, std::decay_t<CArgT>>::serialize(
+ C, std::forward<CArgT>(CArg)))
return Err;
if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
return Err;
- return SequenceSerialization<ChannelT, ArgTs...>::
- serialize(C, std::forward<CArgTs>(CArgs)...);
+ return SequenceSerialization<ChannelT, ArgTs...>::serialize(
+ C, std::forward<CArgTs>(CArgs)...);
}
template <typename CArgT, typename... CArgTs>
- static Error deserialize(ChannelT &C, CArgT &CArg,
- CArgTs &... CArgs) {
+ static Error deserialize(ChannelT &C, CArgT &CArg, CArgTs &...CArgs) {
if (auto Err =
- SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
+ SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
return Err;
if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
return Err;
@@ -315,25 +304,23 @@
};
template <typename ChannelT, typename... ArgTs>
-Error serializeSeq(ChannelT &C, ArgTs &&... Args) {
- return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>::
- serialize(C, std::forward<ArgTs>(Args)...);
+Error serializeSeq(ChannelT &C, ArgTs &&...Args) {
+ return SequenceSerialization<ChannelT, std::decay_t<ArgTs>...>::serialize(
+ C, std::forward<ArgTs>(Args)...);
}
template <typename ChannelT, typename... ArgTs>
-Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
+Error deserializeSeq(ChannelT &C, ArgTs &...Args) {
return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
}
-template <typename ChannelT>
-class SerializationTraits<ChannelT, Error> {
+template <typename ChannelT> class SerializationTraits<ChannelT, Error> {
public:
-
using WrappedErrorSerializer =
- std::function<Error(ChannelT &C, const ErrorInfoBase&)>;
+ std::function<Error(ChannelT &C, const ErrorInfoBase &)>;
using WrappedErrorDeserializer =
- std::function<Error(ChannelT &C, Error &Err)>;
+ std::function<Error(ChannelT &C, Error &Err)>;
template <typename ErrorInfoT, typename SerializeFtor,
typename DeserializeFtor>
@@ -344,24 +331,23 @@
const std::string *KeyName = nullptr;
{
- // We're abusing the stability of std::map here: We take a reference to the
- // key of the deserializers map to save us from duplicating the string in
- // the serializer. This should be changed to use a stringpool if we switch
- // to a map type that may move keys in memory.
+ // We're abusing the stability of std::map here: We take a reference to
+ // the key of the deserializers map to save us from duplicating the string
+ // in the serializer. This should be changed to use a stringpool if we
+ // switch to a map type that may move keys in memory.
std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
- auto I =
- Deserializers.insert(Deserializers.begin(),
- std::make_pair(std::move(Name),
- std::move(Deserialize)));
+ auto I = Deserializers.insert(
+ Deserializers.begin(),
+ std::make_pair(std::move(Name), std::move(Deserialize)));
KeyName = &I->first;
}
{
assert(KeyName != nullptr && "No keyname pointer");
std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
- // FIXME: Move capture Serialize once we have C++14.
Serializers[ErrorInfoT::classID()] =
- [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
+ [KeyName, Serialize = std::move(Serialize)](
+ ChannelT &C, const ErrorInfoBase &EIB) -> Error {
assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&
"Serializer called for wrong error type");
if (auto Err = serializeSeq(C, *KeyName))
@@ -377,13 +363,12 @@
if (!Err)
return serializeSeq(C, std::string());
- return handleErrors(std::move(Err),
- [&C](const ErrorInfoBase &EIB) {
- auto SI = Serializers.find(EIB.dynamicClassID());
- if (SI == Serializers.end())
- return serializeAsStringError(C, EIB);
- return (SI->second)(C, EIB);
- });
+ return handleErrors(std::move(Err), [&C](const ErrorInfoBase &EIB) {
+ auto SI = Serializers.find(EIB.dynamicClassID());
+ if (SI == Serializers.end())
+ return serializeAsStringError(C, EIB);
+ return (SI->second)(C, EIB);
+ });
}
static Error deserialize(ChannelT &C, Error &Err) {
@@ -405,7 +390,6 @@
}
private:
-
static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) {
std::string ErrMsg;
{
@@ -418,7 +402,7 @@
static std::recursive_mutex SerializersMutex;
static std::recursive_mutex DeserializersMutex;
- static std::map<const void*, WrappedErrorSerializer> Serializers;
+ static std::map<const void *, WrappedErrorSerializer> Serializers;
static std::map<std::string, WrappedErrorDeserializer> Deserializers;
};
@@ -429,14 +413,14 @@
std::recursive_mutex SerializationTraits<ChannelT, Error>::DeserializersMutex;
template <typename ChannelT>
-std::map<const void*,
+std::map<const void *,
typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer>
-SerializationTraits<ChannelT, Error>::Serializers;
+ SerializationTraits<ChannelT, Error>::Serializers;
template <typename ChannelT>
-std::map<std::string,
- typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer>
-SerializationTraits<ChannelT, Error>::Deserializers;
+std::map<std::string, typename SerializationTraits<
+ ChannelT, Error>::WrappedErrorDeserializer>
+ SerializationTraits<ChannelT, Error>::Deserializers;
/// Registers a serializer and deserializer for the given error type on the
/// given channel type.
@@ -445,32 +429,29 @@
void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize,
DeserializeFtor &&Deserialize) {
SerializationTraits<ChannelT, Error>::template registerErrorType<ErrorInfoT>(
- std::move(Name),
- std::forward<SerializeFtor>(Serialize),
- std::forward<DeserializeFtor>(Deserialize));
+ std::move(Name), std::forward<SerializeFtor>(Serialize),
+ std::forward<DeserializeFtor>(Deserialize));
}
/// Registers serialization/deserialization for StringError.
-template <typename ChannelT>
-void registerStringError() {
+template <typename ChannelT> void registerStringError() {
static bool AlreadyRegistered = false;
if (!AlreadyRegistered) {
registerErrorSerialization<ChannelT, StringError>(
- "StringError",
- [](ChannelT &C, const StringError &SE) {
- return serializeSeq(C, SE.getMessage());
- },
- [](ChannelT &C, Error &Err) -> Error {
- ErrorAsOutParameter EAO(&Err);
- std::string Msg;
- if (auto E2 = deserializeSeq(C, Msg))
- return E2;
- Err =
- make_error<StringError>(std::move(Msg),
- orcError(
- OrcErrorCode::UnknownErrorCodeFromRemote));
- return Error::success();
- });
+ "StringError",
+ [](ChannelT &C, const StringError &SE) {
+ return serializeSeq(C, SE.getMessage());
+ },
+ [](ChannelT &C, Error &Err) -> Error {
+ ErrorAsOutParameter EAO(&Err);
+ std::string Msg;
+ if (auto E2 = deserializeSeq(C, Msg))
+ return E2;
+ Err = make_error<StringError>(
+ std::move(Msg),
+ orcError(OrcErrorCode::UnknownErrorCodeFromRemote));
+ return Error::success();
+ });
AlreadyRegistered = true;
}
}
@@ -479,7 +460,6 @@
template <typename ChannelT, typename T1, typename T2>
class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> {
public:
-
static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) {
if (ValOrErr) {
if (auto Err = serializeSeq(C, true))
@@ -510,7 +490,6 @@
template <typename ChannelT, typename T1, typename T2>
class SerializationTraits<ChannelT, Expected<T1>, T2> {
public:
-
static Error serialize(ChannelT &C, T2 &&Val) {
return serializeSeq(C, Expected<T2>(std::forward<T2>(Val)));
}
@@ -520,7 +499,6 @@
template <typename ChannelT, typename T>
class SerializationTraits<ChannelT, Expected<T>, Error> {
public:
-
static Error serialize(ChannelT &C, Error &&Err) {
return serializeSeq(C, Expected<T>(std::move(Err)));
}
@@ -548,38 +526,61 @@
template <typename ChannelT, typename... ArgTs>
class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
public:
-
/// RPC channel serialization for std::tuple.
static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
- return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
+ return serializeTupleHelper(C, V, std::index_sequence_for<ArgTs...>());
}
/// RPC channel deserialization for std::tuple.
static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
- return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
+ return deserializeTupleHelper(C, V, std::index_sequence_for<ArgTs...>());
}
private:
// Serialization helper for std::tuple.
template <size_t... Is>
static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
- llvm::index_sequence<Is...> _) {
+ std::index_sequence<Is...> _) {
return serializeSeq(C, std::get<Is>(V)...);
}
// Serialization helper for std::tuple.
template <size_t... Is>
static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
- llvm::index_sequence<Is...> _) {
+ std::index_sequence<Is...> _) {
return deserializeSeq(C, std::get<Is>(V)...);
}
};
+template <typename ChannelT, typename T>
+class SerializationTraits<ChannelT, Optional<T>> {
+public:
+ /// Serialize an Optional<T>.
+ static Error serialize(ChannelT &C, const Optional<T> &O) {
+ if (auto Err = serializeSeq(C, O != None))
+ return Err;
+ if (O)
+ if (auto Err = serializeSeq(C, *O))
+ return Err;
+ return Error::success();
+ }
+
+ /// Deserialize an Optional<T>.
+ static Error deserialize(ChannelT &C, Optional<T> &O) {
+ bool HasValue = false;
+ if (auto Err = deserializeSeq(C, HasValue))
+ return Err;
+ if (HasValue)
+ if (auto Err = deserializeSeq(C, *O))
+ return Err;
+ return Error::success();
+ };
+};
+
/// SerializationTraits default specialization for std::vector.
template <typename ChannelT, typename T>
class SerializationTraits<ChannelT, std::vector<T>> {
public:
-
/// Serialize a std::vector<T> from std::vector<T>.
static Error serialize(ChannelT &C, const std::vector<T> &V) {
if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
@@ -610,6 +611,22 @@
}
};
+/// Enable vector serialization from an ArrayRef.
+template <typename ChannelT, typename T>
+class SerializationTraits<ChannelT, std::vector<T>, ArrayRef<T>> {
+public:
+ static Error serialize(ChannelT &C, ArrayRef<T> V) {
+ if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
+ return Err;
+
+ for (const auto &E : V)
+ if (auto Err = serializeSeq(C, E))
+ return Err;
+
+ return Error::success();
+ }
+};
+
template <typename ChannelT, typename T, typename T2>
class SerializationTraits<ChannelT, std::set<T>, std::set<T2>> {
public:
@@ -696,8 +713,57 @@
}
};
-} // end namespace rpc
+template <typename ChannelT, typename K, typename V, typename K2, typename V2>
+class SerializationTraits<ChannelT, std::map<K, V>, DenseMap<K2, V2>> {
+public:
+ /// Serialize a std::map<K, V> from DenseMap<K2, V2>.
+ static Error serialize(ChannelT &C, const DenseMap<K2, V2> &M) {
+ if (auto Err = serializeSeq(C, static_cast<uint64_t>(M.size())))
+ return Err;
+
+ for (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();
+ }
+
+ /// Serialize a std::map<K, V> from DenseMap<K2, V2>.
+ static Error deserialize(ChannelT &C, DenseMap<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();
+ }
+};
+
+} // namespace shared
} // end namespace orc
} // end namespace llvm
-#endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
+#endif // LLVM_EXECUTIONENGINE_ORC_RPC_RPCSERIALIZATION_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
new file mode 100644
index 0000000..f43b929
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
@@ -0,0 +1,174 @@
+//===--- TargetProcessControlTypes.h -- Shared Core/TPC types ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// TargetProcessControl types that are used by both the Orc and
+// OrcTargetProcess libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+
+#include <vector>
+
+namespace llvm {
+namespace orc {
+namespace tpctypes {
+
+template <typename T> struct UIntWrite {
+ UIntWrite() = default;
+ UIntWrite(JITTargetAddress Address, T Value)
+ : Address(Address), Value(Value) {}
+
+ JITTargetAddress Address = 0;
+ T Value = 0;
+};
+
+/// Describes a write to a uint8_t.
+using UInt8Write = UIntWrite<uint8_t>;
+
+/// Describes a write to a uint16_t.
+using UInt16Write = UIntWrite<uint16_t>;
+
+/// Describes a write to a uint32_t.
+using UInt32Write = UIntWrite<uint32_t>;
+
+/// Describes a write to a uint64_t.
+using UInt64Write = UIntWrite<uint64_t>;
+
+/// Describes a write to a buffer.
+/// For use with TargetProcessControl::MemoryAccess objects.
+struct BufferWrite {
+ BufferWrite() = default;
+ BufferWrite(JITTargetAddress Address, StringRef Buffer)
+ : Address(Address), Buffer(Buffer) {}
+
+ JITTargetAddress Address = 0;
+ StringRef Buffer;
+};
+
+/// A handle used to represent a loaded dylib in the target process.
+using DylibHandle = JITTargetAddress;
+
+/// A pair of a dylib and a set of symbols to be looked up.
+struct LookupRequest {
+ LookupRequest(DylibHandle Handle, const SymbolLookupSet &Symbols)
+ : Handle(Handle), Symbols(Symbols) {}
+ DylibHandle Handle;
+ const SymbolLookupSet &Symbols;
+};
+
+using LookupResult = std::vector<JITTargetAddress>;
+
+/// Either a uint8_t array or a uint8_t*.
+union CWrapperFunctionResultData {
+ uint8_t Value[8];
+ uint8_t *ValuePtr;
+};
+
+/// C ABI compatible wrapper function result.
+///
+/// This can be safely returned from extern "C" functions, but should be used
+/// to construct a WrapperFunctionResult for safety.
+struct CWrapperFunctionResult {
+ uint64_t Size;
+ CWrapperFunctionResultData Data;
+ void (*Destroy)(CWrapperFunctionResultData Data, uint64_t Size);
+};
+
+/// C++ wrapper function result: Same as CWrapperFunctionResult but
+/// auto-releases memory.
+class WrapperFunctionResult {
+public:
+ /// Create a default WrapperFunctionResult.
+ WrapperFunctionResult() { zeroInit(R); }
+
+ /// Create a WrapperFunctionResult from a CWrapperFunctionResult. This
+ /// instance takes ownership of the result object and will automatically
+ /// call the Destroy member upon destruction.
+ WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {}
+
+ WrapperFunctionResult(const WrapperFunctionResult &) = delete;
+ WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
+
+ WrapperFunctionResult(WrapperFunctionResult &&Other) {
+ zeroInit(R);
+ std::swap(R, Other.R);
+ }
+
+ WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
+ CWrapperFunctionResult Tmp;
+ zeroInit(Tmp);
+ std::swap(Tmp, Other.R);
+ std::swap(R, Tmp);
+ return *this;
+ }
+
+ ~WrapperFunctionResult() {
+ if (R.Destroy)
+ R.Destroy(R.Data, R.Size);
+ }
+
+ /// Relinquish ownership of and return the CWrapperFunctionResult.
+ CWrapperFunctionResult release() {
+ CWrapperFunctionResult Tmp;
+ zeroInit(Tmp);
+ std::swap(R, Tmp);
+ return Tmp;
+ }
+
+ /// Get an ArrayRef covering the data in the result.
+ ArrayRef<uint8_t> getData() const {
+ if (R.Size <= 8)
+ return ArrayRef<uint8_t>(R.Data.Value, R.Size);
+ return ArrayRef<uint8_t>(R.Data.ValuePtr, R.Size);
+ }
+
+ /// Create a WrapperFunctionResult from the given integer, provided its
+ /// size is no greater than 64 bits.
+ template <typename T,
+ typename _ = std::enable_if_t<std::is_integral<T>::value &&
+ sizeof(T) <= sizeof(uint64_t)>>
+ static WrapperFunctionResult from(T Value) {
+ CWrapperFunctionResult R;
+ R.Size = sizeof(T);
+ memcpy(&R.Data.Value, Value, R.Size);
+ R.Destroy = nullptr;
+ return R;
+ }
+
+ /// Create a WrapperFunctionResult from the given string.
+ static WrapperFunctionResult from(StringRef S);
+
+ /// Always free Data.ValuePtr by calling free on it.
+ static void destroyWithFree(CWrapperFunctionResultData Data, uint64_t Size);
+
+ /// Always free Data.ValuePtr by calling delete[] on it.
+ static void destroyWithDeleteArray(CWrapperFunctionResultData Data,
+ uint64_t Size);
+
+private:
+ static void zeroInit(CWrapperFunctionResult &R) {
+ R.Size = 0;
+ R.Data.ValuePtr = nullptr;
+ R.Destroy = nullptr;
+ }
+
+ CWrapperFunctionResult R;
+};
+
+} // end namespace tpctypes
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SpeculateAnalyses.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SpeculateAnalyses.h
new file mode 100644
index 0000000..cf57b63
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SpeculateAnalyses.h
@@ -0,0 +1,84 @@
+//===-- SpeculateAnalyses.h --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// \file
+/// Contains the Analyses and Result Interpretation to select likely functions
+/// to Speculatively compile before they are called. [Purely Experimentation]
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SPECULATEANALYSES_H
+#define LLVM_EXECUTIONENGINE_ORC_SPECULATEANALYSES_H
+
+#include "llvm/Analysis/BranchProbabilityInfo.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Speculation.h"
+
+#include <vector>
+
+namespace llvm {
+
+namespace orc {
+
+// Provides common code.
+class SpeculateQuery {
+protected:
+ void findCalles(const BasicBlock *, DenseSet<StringRef> &);
+ bool isStraightLine(const Function &F);
+
+public:
+ using ResultTy = Optional<DenseMap<StringRef, DenseSet<StringRef>>>;
+};
+
+// Direct calls in high frequency basic blocks are extracted.
+class BlockFreqQuery : public SpeculateQuery {
+ size_t numBBToGet(size_t);
+
+public:
+ // Find likely next executables based on IR Block Frequency
+ ResultTy operator()(Function &F);
+};
+
+// This Query generates a sequence of basic blocks which follows the order of
+// execution.
+// A handful of BB with higher block frequencies are taken, then path to entry
+// and end BB are discovered by traversing up & down the CFG.
+class SequenceBBQuery : public SpeculateQuery {
+ struct WalkDirection {
+ bool Upward = true, Downward = true;
+ // the block associated contain a call
+ bool CallerBlock = false;
+ };
+
+public:
+ using VisitedBlocksInfoTy = DenseMap<const BasicBlock *, WalkDirection>;
+ using BlockListTy = SmallVector<const BasicBlock *, 8>;
+ using BackEdgesInfoTy =
+ SmallVector<std::pair<const BasicBlock *, const BasicBlock *>, 8>;
+ using BlockFreqInfoTy =
+ SmallVector<std::pair<const BasicBlock *, uint64_t>, 8>;
+
+private:
+ std::size_t getHottestBlocks(std::size_t TotalBlocks);
+ BlockListTy rearrangeBB(const Function &, const BlockListTy &);
+ BlockListTy queryCFG(Function &, const BlockListTy &);
+ void traverseToEntryBlock(const BasicBlock *, const BlockListTy &,
+ const BackEdgesInfoTy &,
+ const BranchProbabilityInfo *,
+ VisitedBlocksInfoTy &);
+ void traverseToExitBlock(const BasicBlock *, const BlockListTy &,
+ const BackEdgesInfoTy &,
+ const BranchProbabilityInfo *,
+ VisitedBlocksInfoTy &);
+
+public:
+ ResultTy operator()(Function &F);
+};
+
+} // namespace orc
+} // namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SPECULATEANALYSES_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Speculation.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Speculation.h
new file mode 100644
index 0000000..a138f60
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Speculation.h
@@ -0,0 +1,210 @@
+//===-- Speculation.h - Speculative Compilation --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the definition to support speculative compilation when laziness is
+// enabled.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
+#define LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/Support/Debug.h"
+#include <mutex>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+namespace orc {
+
+class Speculator;
+
+// Track the Impls (JITDylib,Symbols) of Symbols while lazy call through
+// trampolines are created. Operations are guarded by locks tp ensure that Imap
+// stays in consistent state after read/write
+
+class ImplSymbolMap {
+ friend class Speculator;
+
+public:
+ using AliaseeDetails = std::pair<SymbolStringPtr, JITDylib *>;
+ using Alias = SymbolStringPtr;
+ using ImapTy = DenseMap<Alias, AliaseeDetails>;
+ void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD);
+
+private:
+ // FIX ME: find a right way to distinguish the pre-compile Symbols, and update
+ // the callsite
+ Optional<AliaseeDetails> getImplFor(const SymbolStringPtr &StubSymbol) {
+ std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
+ auto Position = Maps.find(StubSymbol);
+ if (Position != Maps.end())
+ return Position->getSecond();
+ else
+ return None;
+ }
+
+ std::mutex ConcurrentAccess;
+ ImapTy Maps;
+};
+
+// Defines Speculator Concept,
+class Speculator {
+public:
+ using TargetFAddr = JITTargetAddress;
+ using FunctionCandidatesMap = DenseMap<SymbolStringPtr, SymbolNameSet>;
+ using StubAddrLikelies = DenseMap<TargetFAddr, SymbolNameSet>;
+
+private:
+ void registerSymbolsWithAddr(TargetFAddr ImplAddr,
+ SymbolNameSet likelySymbols) {
+ std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
+ GlobalSpecMap.insert({ImplAddr, std::move(likelySymbols)});
+ }
+
+ void launchCompile(JITTargetAddress FAddr) {
+ SymbolNameSet CandidateSet;
+ // Copy CandidateSet is necessary, to avoid unsynchronized access to
+ // the datastructure.
+ {
+ std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
+ auto It = GlobalSpecMap.find(FAddr);
+ if (It == GlobalSpecMap.end())
+ return;
+ CandidateSet = It->getSecond();
+ }
+
+ SymbolDependenceMap SpeculativeLookUpImpls;
+
+ for (auto &Callee : CandidateSet) {
+ auto ImplSymbol = AliaseeImplTable.getImplFor(Callee);
+ // try to distinguish already compiled & library symbols
+ if (!ImplSymbol.hasValue())
+ continue;
+ const auto &ImplSymbolName = ImplSymbol.getPointer()->first;
+ JITDylib *ImplJD = ImplSymbol.getPointer()->second;
+ auto &SymbolsInJD = SpeculativeLookUpImpls[ImplJD];
+ SymbolsInJD.insert(ImplSymbolName);
+ }
+
+ DEBUG_WITH_TYPE("orc", {
+ for (auto &I : SpeculativeLookUpImpls) {
+ llvm::dbgs() << "\n In " << I.first->getName() << " JITDylib ";
+ for (auto &N : I.second)
+ llvm::dbgs() << "\n Likely Symbol : " << N;
+ }
+ });
+
+ // for a given symbol, there may be no symbol qualified for speculatively
+ // compile try to fix this before jumping to this code if possible.
+ for (auto &LookupPair : SpeculativeLookUpImpls)
+ ES.lookup(
+ LookupKind::Static,
+ makeJITDylibSearchOrder(LookupPair.first,
+ JITDylibLookupFlags::MatchAllSymbols),
+ SymbolLookupSet(LookupPair.second), SymbolState::Ready,
+ [this](Expected<SymbolMap> Result) {
+ if (auto Err = Result.takeError())
+ ES.reportError(std::move(Err));
+ },
+ NoDependenciesToRegister);
+ }
+
+public:
+ Speculator(ImplSymbolMap &Impl, ExecutionSession &ref)
+ : AliaseeImplTable(Impl), ES(ref), GlobalSpecMap(0) {}
+ Speculator(const Speculator &) = delete;
+ Speculator(Speculator &&) = delete;
+ Speculator &operator=(const Speculator &) = delete;
+ Speculator &operator=(Speculator &&) = delete;
+
+ /// Define symbols for this Speculator object (__orc_speculator) and the
+ /// speculation runtime entry point symbol (__orc_speculate_for) in the
+ /// given JITDylib.
+ Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle);
+
+ // Speculatively compile likely functions for the given Stub Address.
+ // destination of __orc_speculate_for jump
+ void speculateFor(TargetFAddr StubAddr) { launchCompile(StubAddr); }
+
+ // FIXME : Register with Stub Address, after JITLink Fix.
+ void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD) {
+ for (auto &SymPair : Candidates) {
+ auto Target = SymPair.first;
+ auto Likely = SymPair.second;
+
+ auto OnReadyFixUp = [Likely, Target,
+ this](Expected<SymbolMap> ReadySymbol) {
+ if (ReadySymbol) {
+ auto RAddr = (*ReadySymbol)[Target].getAddress();
+ registerSymbolsWithAddr(RAddr, std::move(Likely));
+ } else
+ this->getES().reportError(ReadySymbol.takeError());
+ };
+ // Include non-exported symbols also.
+ ES.lookup(
+ LookupKind::Static,
+ makeJITDylibSearchOrder(JD, JITDylibLookupFlags::MatchAllSymbols),
+ SymbolLookupSet(Target, SymbolLookupFlags::WeaklyReferencedSymbol),
+ SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister);
+ }
+ }
+
+ ExecutionSession &getES() { return ES; }
+
+private:
+ static void speculateForEntryPoint(Speculator *Ptr, uint64_t StubId);
+ std::mutex ConcurrentAccess;
+ ImplSymbolMap &AliaseeImplTable;
+ ExecutionSession &ES;
+ StubAddrLikelies GlobalSpecMap;
+};
+
+class IRSpeculationLayer : public IRLayer {
+public:
+ using IRlikiesStrRef = Optional<DenseMap<StringRef, DenseSet<StringRef>>>;
+ using ResultEval = std::function<IRlikiesStrRef(Function &)>;
+ using TargetAndLikelies = DenseMap<SymbolStringPtr, SymbolNameSet>;
+
+ IRSpeculationLayer(ExecutionSession &ES, IRCompileLayer &BaseLayer,
+ Speculator &Spec, MangleAndInterner &Mangle,
+ ResultEval Interpreter)
+ : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer),
+ S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {}
+
+ void emit(std::unique_ptr<MaterializationResponsibility> R,
+ ThreadSafeModule TSM) override;
+
+private:
+ TargetAndLikelies
+ internToJITSymbols(DenseMap<StringRef, DenseSet<StringRef>> IRNames) {
+ assert(!IRNames.empty() && "No IRNames received to Intern?");
+ TargetAndLikelies InternedNames;
+ for (auto &NamePair : IRNames) {
+ DenseSet<SymbolStringPtr> TargetJITNames;
+ for (auto &TargetNames : NamePair.second)
+ TargetJITNames.insert(Mangle(TargetNames));
+ InternedNames[Mangle(NamePair.first)] = std::move(TargetJITNames);
+ }
+ return InternedNames;
+ }
+
+ IRCompileLayer &NextLayer;
+ Speculator &S;
+ MangleAndInterner &Mangle;
+ ResultEval QueryAnalysis;
+};
+
+} // namespace orc
+} // namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
index c354f6c..c9fadd7 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -48,11 +48,13 @@
/// Pointer to a pooled string representing a symbol name.
class SymbolStringPtr {
+ friend class OrcV2CAPIHelper;
friend class SymbolStringPool;
friend struct DenseMapInfo<SymbolStringPtr>;
public:
SymbolStringPtr() = default;
+ SymbolStringPtr(std::nullptr_t) {}
SymbolStringPtr(const SymbolStringPtr &Other)
: S(Other.S) {
if (isRealPoolEntry(S))
@@ -85,6 +87,8 @@
--S->getValue();
}
+ explicit operator bool() const { return S; }
+
StringRef operator*() const { return S->first(); }
friend bool operator==(const SymbolStringPtr &LHS,
@@ -103,7 +107,8 @@
}
private:
- using PoolEntryPtr = SymbolStringPool::PoolMapEntry *;
+ using PoolEntry = SymbolStringPool::PoolMapEntry;
+ using PoolEntryPtr = PoolEntry *;
SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
: S(S) {
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
new file mode 100644
index 0000000..ed4f608
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
@@ -0,0 +1,66 @@
+//===------------ TPCDynamicLibrarySearchGenerator.h ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Support loading and searching of dynamic libraries in a target process via
+// the TargetProcessControl class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TPCDYNAMICLIBRARYSEARCHGENERATOR_H
+#define LLVM_EXECUTIONENGINE_ORC_TPCDYNAMICLIBRARYSEARCHGENERATOR_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+
+namespace llvm {
+namespace orc {
+
+class TPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
+public:
+ using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>;
+
+ /// Create a DynamicLibrarySearchGenerator that searches for symbols in the
+ /// library with the given handle.
+ ///
+ /// If the Allow predicate is given then only symbols matching the predicate
+ /// will be searched for. If the predicate is not given then all symbols will
+ /// be searched for.
+ TPCDynamicLibrarySearchGenerator(TargetProcessControl &TPC,
+ tpctypes::DylibHandle H,
+ SymbolPredicate Allow = SymbolPredicate())
+ : TPC(TPC), H(H), Allow(std::move(Allow)) {}
+
+ /// Permanently loads the library at the given path and, on success, returns
+ /// a DynamicLibrarySearchGenerator that will search it for symbol definitions
+ /// in the library. On failure returns the reason the library failed to load.
+ static Expected<std::unique_ptr<TPCDynamicLibrarySearchGenerator>>
+ Load(TargetProcessControl &TPC, const char *LibraryPath,
+ SymbolPredicate Allow = SymbolPredicate());
+
+ /// Creates a TPCDynamicLibrarySearchGenerator that searches for symbols in
+ /// the target process.
+ static Expected<std::unique_ptr<TPCDynamicLibrarySearchGenerator>>
+ GetForTargetProcess(TargetProcessControl &TPC,
+ SymbolPredicate Allow = SymbolPredicate()) {
+ return Load(TPC, nullptr, std::move(Allow));
+ }
+
+ Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags,
+ const SymbolLookupSet &Symbols) override;
+
+private:
+ TargetProcessControl &TPC;
+ tpctypes::DylibHandle H;
+ SymbolPredicate Allow;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TPCDYNAMICLIBRARYSEARCHGENERATOR_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h
new file mode 100644
index 0000000..519f818
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h
@@ -0,0 +1,54 @@
+//===-- TPCEHFrameRegistrar.h - TPC based eh-frame registration -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// TargetProcessControl based eh-frame registration.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H
+#define LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H
+
+#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+
+namespace llvm {
+namespace orc {
+
+/// Register/Deregisters EH frames in a remote process via a
+/// TargetProcessControl instance.
+class TPCEHFrameRegistrar : public jitlink::EHFrameRegistrar {
+public:
+ /// Create from a TargetProcessControl instance alone. This will use
+ /// the TPC's lookupSymbols method to find the registration/deregistration
+ /// funciton addresses by name.
+ static Expected<std::unique_ptr<TPCEHFrameRegistrar>>
+ Create(TargetProcessControl &TPC);
+
+ /// Create a TPCEHFrameRegistrar with the given TargetProcessControl
+ /// object and registration/deregistration function addresses.
+ TPCEHFrameRegistrar(TargetProcessControl &TPC,
+ JITTargetAddress RegisterEHFrameWrapperFnAddr,
+ JITTargetAddress DeregisterEHFRameWrapperFnAddr)
+ : TPC(TPC), RegisterEHFrameWrapperFnAddr(RegisterEHFrameWrapperFnAddr),
+ DeregisterEHFrameWrapperFnAddr(DeregisterEHFRameWrapperFnAddr) {}
+
+ Error registerEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) override;
+ Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) override;
+
+private:
+ TargetProcessControl &TPC;
+ JITTargetAddress RegisterEHFrameWrapperFnAddr;
+ JITTargetAddress DeregisterEHFrameWrapperFnAddr;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h
new file mode 100644
index 0000000..e7abd7f
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h
@@ -0,0 +1,222 @@
+//===--- TPCIndirectionUtils.h - TPC based indirection utils ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Indirection utilities (stubs, trampolines, lazy call-throughs) that use the
+// TargetProcessControl API to interact with the target process.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
+
+#include <mutex>
+
+namespace llvm {
+namespace orc {
+
+class TargetProcessControl;
+
+/// Provides TargetProcessControl based indirect stubs, trampoline pool and
+/// lazy call through manager.
+class TPCIndirectionUtils {
+ friend class TPCIndirectionUtilsAccess;
+
+public:
+ /// ABI support base class. Used to write resolver, stub, and trampoline
+ /// blocks.
+ class ABISupport {
+ protected:
+ ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize,
+ unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize)
+ : PointerSize(PointerSize), TrampolineSize(TrampolineSize),
+ StubSize(StubSize),
+ StubToPointerMaxDisplacement(StubToPointerMaxDisplacement),
+ ResolverCodeSize(ResolverCodeSize) {}
+
+ public:
+ virtual ~ABISupport();
+
+ unsigned getPointerSize() const { return PointerSize; }
+ unsigned getTrampolineSize() const { return TrampolineSize; }
+ unsigned getStubSize() const { return StubSize; }
+ unsigned getStubToPointerMaxDisplacement() const {
+ return StubToPointerMaxDisplacement;
+ }
+ unsigned getResolverCodeSize() const { return ResolverCodeSize; }
+
+ virtual void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddr,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) const = 0;
+
+ virtual void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTragetAddr,
+ JITTargetAddress ResolverAddr,
+ unsigned NumTrampolines) const = 0;
+
+ virtual void
+ writeIndirectStubsBlock(char *StubsBlockWorkingMem,
+ JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress,
+ unsigned NumStubs) const = 0;
+
+ private:
+ unsigned PointerSize = 0;
+ unsigned TrampolineSize = 0;
+ unsigned StubSize = 0;
+ unsigned StubToPointerMaxDisplacement = 0;
+ unsigned ResolverCodeSize = 0;
+ };
+
+ /// Create using the given ABI class.
+ template <typename ORCABI>
+ static std::unique_ptr<TPCIndirectionUtils>
+ CreateWithABI(TargetProcessControl &TPC);
+
+ /// Create based on the TargetProcessControl triple.
+ static Expected<std::unique_ptr<TPCIndirectionUtils>>
+ Create(TargetProcessControl &TPC);
+
+ /// Return a reference to the TargetProcessControl object.
+ TargetProcessControl &getTargetProcessControl() const { return TPC; }
+
+ /// Return a reference to the ABISupport object for this instance.
+ ABISupport &getABISupport() const { return *ABI; }
+
+ /// Release memory for resources held by this instance. This *must* be called
+ /// prior to destruction of the class.
+ Error cleanup();
+
+ /// Write resolver code to the target process and return its address.
+ /// This must be called before any call to createTrampolinePool or
+ /// createLazyCallThroughManager.
+ Expected<JITTargetAddress>
+ writeResolverBlock(JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr);
+
+ /// Returns the address of the Resolver block. Returns zero if the
+ /// writeResolverBlock method has not previously been called.
+ JITTargetAddress getResolverBlockAddress() const { return ResolverBlockAddr; }
+
+ /// Create an IndirectStubsManager for the target process.
+ std::unique_ptr<IndirectStubsManager> createIndirectStubsManager();
+
+ /// Create a TrampolinePool for the target process.
+ TrampolinePool &getTrampolinePool();
+
+ /// Create a LazyCallThroughManager.
+ /// This function should only be called once.
+ LazyCallThroughManager &
+ createLazyCallThroughManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddr);
+
+ /// Create a LazyCallThroughManager for the target process.
+ LazyCallThroughManager &getLazyCallThroughManager() {
+ assert(LCTM && "createLazyCallThroughManager must be called first");
+ return *LCTM;
+ }
+
+private:
+ using Allocation = jitlink::JITLinkMemoryManager::Allocation;
+
+ struct IndirectStubInfo {
+ IndirectStubInfo() = default;
+ IndirectStubInfo(JITTargetAddress StubAddress,
+ JITTargetAddress PointerAddress)
+ : StubAddress(StubAddress), PointerAddress(PointerAddress) {}
+ JITTargetAddress StubAddress = 0;
+ JITTargetAddress PointerAddress = 0;
+ };
+
+ using IndirectStubInfoVector = std::vector<IndirectStubInfo>;
+
+ /// Create a TPCIndirectionUtils instance.
+ TPCIndirectionUtils(TargetProcessControl &TPC,
+ std::unique_ptr<ABISupport> ABI);
+
+ Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs);
+
+ std::mutex TPCUIMutex;
+ TargetProcessControl &TPC;
+ std::unique_ptr<ABISupport> ABI;
+ JITTargetAddress ResolverBlockAddr;
+ std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> ResolverBlock;
+ std::unique_ptr<TrampolinePool> TP;
+ std::unique_ptr<LazyCallThroughManager> LCTM;
+
+ std::vector<IndirectStubInfo> AvailableIndirectStubs;
+ std::vector<std::unique_ptr<Allocation>> IndirectStubAllocs;
+};
+
+/// This will call writeResolver on the given TPCIndirectionUtils instance
+/// to set up re-entry via a function that will directly return the trampoline
+/// landing address.
+///
+/// The TPCIndirectionUtils' LazyCallThroughManager must have been previously
+/// created via TPCIndirectionUtils::createLazyCallThroughManager.
+///
+/// The TPCIndirectionUtils' writeResolver method must not have been previously
+/// called.
+///
+/// This function is experimental and likely subject to revision.
+Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU);
+
+namespace detail {
+
+template <typename ORCABI>
+class ABISupportImpl : public TPCIndirectionUtils::ABISupport {
+public:
+ ABISupportImpl()
+ : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize,
+ ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement,
+ ORCABI::ResolverCodeSize) {}
+
+ void writeResolverCode(char *ResolverWorkingMem,
+ JITTargetAddress ResolverTargetAddr,
+ JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) const override {
+ ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr,
+ ReentryFnAddr, ReentryCtxAddr);
+ }
+
+ void writeTrampolines(char *TrampolineBlockWorkingMem,
+ JITTargetAddress TrampolineBlockTargetAddr,
+ JITTargetAddress ResolverAddr,
+ unsigned NumTrampolines) const override {
+ ORCABI::writeTrampolines(TrampolineBlockWorkingMem,
+ TrampolineBlockTargetAddr, ResolverAddr,
+ NumTrampolines);
+ }
+
+ void writeIndirectStubsBlock(char *StubsBlockWorkingMem,
+ JITTargetAddress StubsBlockTargetAddress,
+ JITTargetAddress PointersBlockTargetAddress,
+ unsigned NumStubs) const override {
+ ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem,
+ StubsBlockTargetAddress,
+ PointersBlockTargetAddress, NumStubs);
+ }
+};
+
+} // end namespace detail
+
+template <typename ORCABI>
+std::unique_ptr<TPCIndirectionUtils>
+TPCIndirectionUtils::CreateWithABI(TargetProcessControl &TPC) {
+ return std::unique_ptr<TPCIndirectionUtils>(new TPCIndirectionUtils(
+ TPC, std::make_unique<detail::ABISupportImpl<ORCABI>>()));
+}
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h
new file mode 100644
index 0000000..253e06b
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h
@@ -0,0 +1,620 @@
+//===-- OrcRPCTPCServer.h -- OrcRPCTargetProcessControl Server --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// OrcRPCTargetProcessControl server class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
+
+#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Process.h"
+
+#include <atomic>
+
+namespace llvm {
+namespace orc {
+
+namespace orcrpctpc {
+
+enum WireProtectionFlags : uint8_t {
+ WPF_None = 0,
+ WPF_Read = 1U << 0,
+ WPF_Write = 1U << 1,
+ WPF_Exec = 1U << 2,
+ LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec)
+};
+
+/// Convert from sys::Memory::ProtectionFlags
+inline WireProtectionFlags
+toWireProtectionFlags(sys::Memory::ProtectionFlags PF) {
+ WireProtectionFlags WPF = WPF_None;
+ if (PF & sys::Memory::MF_READ)
+ WPF |= WPF_Read;
+ if (PF & sys::Memory::MF_WRITE)
+ WPF |= WPF_Write;
+ if (PF & sys::Memory::MF_EXEC)
+ WPF |= WPF_Exec;
+ return WPF;
+}
+
+inline sys::Memory::ProtectionFlags
+fromWireProtectionFlags(WireProtectionFlags WPF) {
+ int PF = 0;
+ if (WPF & WPF_Read)
+ PF |= sys::Memory::MF_READ;
+ if (WPF & WPF_Write)
+ PF |= sys::Memory::MF_WRITE;
+ if (WPF & WPF_Exec)
+ PF |= sys::Memory::MF_EXEC;
+ return static_cast<sys::Memory::ProtectionFlags>(PF);
+}
+
+struct ReserveMemRequestElement {
+ WireProtectionFlags Prot = WPF_None;
+ uint64_t Size = 0;
+ uint64_t Alignment = 0;
+};
+
+using ReserveMemRequest = std::vector<ReserveMemRequestElement>;
+
+struct ReserveMemResultElement {
+ WireProtectionFlags Prot = WPF_None;
+ JITTargetAddress Address = 0;
+ uint64_t AllocatedSize = 0;
+};
+
+using ReserveMemResult = std::vector<ReserveMemResultElement>;
+
+struct ReleaseOrFinalizeMemRequestElement {
+ WireProtectionFlags Prot = WPF_None;
+ JITTargetAddress Address = 0;
+ uint64_t Size = 0;
+};
+
+using ReleaseOrFinalizeMemRequest =
+ std::vector<ReleaseOrFinalizeMemRequestElement>;
+
+} // end namespace orcrpctpc
+
+namespace shared {
+
+template <> class SerializationTypeName<tpctypes::UInt8Write> {
+public:
+ static const char *getName() { return "UInt8Write"; }
+};
+
+template <> class SerializationTypeName<tpctypes::UInt16Write> {
+public:
+ static const char *getName() { return "UInt16Write"; }
+};
+
+template <> class SerializationTypeName<tpctypes::UInt32Write> {
+public:
+ static const char *getName() { return "UInt32Write"; }
+};
+
+template <> class SerializationTypeName<tpctypes::UInt64Write> {
+public:
+ static const char *getName() { return "UInt64Write"; }
+};
+
+template <> class SerializationTypeName<tpctypes::BufferWrite> {
+public:
+ static const char *getName() { return "BufferWrite"; }
+};
+
+template <> class SerializationTypeName<orcrpctpc::ReserveMemRequestElement> {
+public:
+ static const char *getName() { return "ReserveMemRequestElement"; }
+};
+
+template <> class SerializationTypeName<orcrpctpc::ReserveMemResultElement> {
+public:
+ static const char *getName() { return "ReserveMemResultElement"; }
+};
+
+template <>
+class SerializationTypeName<orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
+public:
+ static const char *getName() { return "ReleaseOrFinalizeMemRequestElement"; }
+};
+
+template <> class SerializationTypeName<tpctypes::WrapperFunctionResult> {
+public:
+ static const char *getName() { return "WrapperFunctionResult"; }
+};
+
+template <typename ChannelT, typename WriteT>
+class SerializationTraits<
+ ChannelT, WriteT, WriteT,
+ std::enable_if_t<std::is_same<WriteT, tpctypes::UInt8Write>::value ||
+ std::is_same<WriteT, tpctypes::UInt16Write>::value ||
+ std::is_same<WriteT, tpctypes::UInt32Write>::value ||
+ std::is_same<WriteT, tpctypes::UInt64Write>::value>> {
+public:
+ static Error serialize(ChannelT &C, const WriteT &W) {
+ return serializeSeq(C, W.Address, W.Value);
+ }
+ static Error deserialize(ChannelT &C, WriteT &W) {
+ return deserializeSeq(C, W.Address, W.Value);
+ }
+};
+
+template <typename ChannelT>
+class SerializationTraits<
+ ChannelT, tpctypes::BufferWrite, tpctypes::BufferWrite,
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
+public:
+ static Error serialize(ChannelT &C, const tpctypes::BufferWrite &W) {
+ uint64_t Size = W.Buffer.size();
+ if (auto Err = serializeSeq(C, W.Address, Size))
+ return Err;
+
+ return C.appendBytes(W.Buffer.data(), Size);
+ }
+ static Error deserialize(ChannelT &C, tpctypes::BufferWrite &W) {
+ JITTargetAddress Address;
+ uint64_t Size;
+
+ if (auto Err = deserializeSeq(C, Address, Size))
+ return Err;
+
+ char *Buffer = jitTargetAddressToPointer<char *>(Address);
+
+ if (auto Err = C.readBytes(Buffer, Size))
+ return Err;
+
+ W = {Address, StringRef(Buffer, Size)};
+ return Error::success();
+ }
+};
+
+template <typename ChannelT>
+class SerializationTraits<ChannelT, orcrpctpc::ReserveMemRequestElement> {
+public:
+ static Error serialize(ChannelT &C,
+ const orcrpctpc::ReserveMemRequestElement &E) {
+ return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Size, E.Alignment);
+ }
+
+ static Error deserialize(ChannelT &C,
+ orcrpctpc::ReserveMemRequestElement &E) {
+ return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Size,
+ E.Alignment);
+ }
+};
+
+template <typename ChannelT>
+class SerializationTraits<ChannelT, orcrpctpc::ReserveMemResultElement> {
+public:
+ static Error serialize(ChannelT &C,
+ const orcrpctpc::ReserveMemResultElement &E) {
+ return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address,
+ E.AllocatedSize);
+ }
+
+ static Error deserialize(ChannelT &C, orcrpctpc::ReserveMemResultElement &E) {
+ return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address,
+ E.AllocatedSize);
+ }
+};
+
+template <typename ChannelT>
+class SerializationTraits<ChannelT,
+ orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
+public:
+ static Error
+ serialize(ChannelT &C,
+ const orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
+ return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address, E.Size);
+ }
+
+ static Error deserialize(ChannelT &C,
+ orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
+ return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address,
+ E.Size);
+ }
+};
+
+template <typename ChannelT>
+class SerializationTraits<
+ ChannelT, tpctypes::WrapperFunctionResult, tpctypes::WrapperFunctionResult,
+ std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
+public:
+ static Error serialize(ChannelT &C,
+ const tpctypes::WrapperFunctionResult &E) {
+ auto Data = E.getData();
+ if (auto Err = serializeSeq(C, static_cast<uint64_t>(Data.size())))
+ return Err;
+ if (Data.size() == 0)
+ return Error::success();
+ return C.appendBytes(reinterpret_cast<const char *>(Data.data()),
+ Data.size());
+ }
+
+ static Error deserialize(ChannelT &C, tpctypes::WrapperFunctionResult &E) {
+ tpctypes::CWrapperFunctionResult R;
+
+ R.Size = 0;
+ R.Data.ValuePtr = nullptr;
+ R.Destroy = nullptr;
+
+ if (auto Err = deserializeSeq(C, R.Size))
+ return Err;
+ if (R.Size == 0)
+ return Error::success();
+ R.Data.ValuePtr = new uint8_t[R.Size];
+ if (auto Err =
+ C.readBytes(reinterpret_cast<char *>(R.Data.ValuePtr), R.Size)) {
+ R.Destroy = tpctypes::WrapperFunctionResult::destroyWithDeleteArray;
+ return Err;
+ }
+
+ E = tpctypes::WrapperFunctionResult(R);
+ return Error::success();
+ }
+};
+
+} // end namespace shared
+
+namespace orcrpctpc {
+
+using RemoteSymbolLookupSet = std::vector<std::pair<std::string, bool>>;
+using RemoteLookupRequest =
+ std::pair<tpctypes::DylibHandle, RemoteSymbolLookupSet>;
+
+class GetTargetTriple
+ : public shared::RPCFunction<GetTargetTriple, std::string()> {
+public:
+ static const char *getName() { return "GetTargetTriple"; }
+};
+
+class GetPageSize : public shared::RPCFunction<GetPageSize, uint64_t()> {
+public:
+ static const char *getName() { return "GetPageSize"; }
+};
+
+class ReserveMem
+ : public shared::RPCFunction<ReserveMem, Expected<ReserveMemResult>(
+ ReserveMemRequest)> {
+public:
+ static const char *getName() { return "ReserveMem"; }
+};
+
+class FinalizeMem
+ : public shared::RPCFunction<FinalizeMem,
+ Error(ReleaseOrFinalizeMemRequest)> {
+public:
+ static const char *getName() { return "FinalizeMem"; }
+};
+
+class ReleaseMem
+ : public shared::RPCFunction<ReleaseMem,
+ Error(ReleaseOrFinalizeMemRequest)> {
+public:
+ static const char *getName() { return "ReleaseMem"; }
+};
+
+class WriteUInt8s
+ : public shared::RPCFunction<WriteUInt8s,
+ Error(std::vector<tpctypes::UInt8Write>)> {
+public:
+ static const char *getName() { return "WriteUInt8s"; }
+};
+
+class WriteUInt16s
+ : public shared::RPCFunction<WriteUInt16s,
+ Error(std::vector<tpctypes::UInt16Write>)> {
+public:
+ static const char *getName() { return "WriteUInt16s"; }
+};
+
+class WriteUInt32s
+ : public shared::RPCFunction<WriteUInt32s,
+ Error(std::vector<tpctypes::UInt32Write>)> {
+public:
+ static const char *getName() { return "WriteUInt32s"; }
+};
+
+class WriteUInt64s
+ : public shared::RPCFunction<WriteUInt64s,
+ Error(std::vector<tpctypes::UInt64Write>)> {
+public:
+ static const char *getName() { return "WriteUInt64s"; }
+};
+
+class WriteBuffers
+ : public shared::RPCFunction<WriteBuffers,
+ Error(std::vector<tpctypes::BufferWrite>)> {
+public:
+ static const char *getName() { return "WriteBuffers"; }
+};
+
+class LoadDylib
+ : public shared::RPCFunction<LoadDylib, Expected<tpctypes::DylibHandle>(
+ std::string DylibPath)> {
+public:
+ static const char *getName() { return "LoadDylib"; }
+};
+
+class LookupSymbols
+ : public shared::RPCFunction<LookupSymbols,
+ Expected<std::vector<tpctypes::LookupResult>>(
+ std::vector<RemoteLookupRequest>)> {
+public:
+ static const char *getName() { return "LookupSymbols"; }
+};
+
+class RunMain
+ : public shared::RPCFunction<RunMain,
+ int32_t(JITTargetAddress MainAddr,
+ std::vector<std::string> Args)> {
+public:
+ static const char *getName() { return "RunMain"; }
+};
+
+class RunWrapper
+ : public shared::RPCFunction<RunWrapper,
+ tpctypes::WrapperFunctionResult(
+ JITTargetAddress, std::vector<uint8_t>)> {
+public:
+ static const char *getName() { return "RunWrapper"; }
+};
+
+class CloseConnection : public shared::RPCFunction<CloseConnection, void()> {
+public:
+ static const char *getName() { return "CloseConnection"; }
+};
+
+} // end namespace orcrpctpc
+
+/// TargetProcessControl for a process connected via an ORC RPC Endpoint.
+template <typename RPCEndpointT> class OrcRPCTPCServer {
+public:
+ /// Create an OrcRPCTPCServer from the given endpoint.
+ OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) {
+ using ThisT = OrcRPCTPCServer<RPCEndpointT>;
+
+ TripleStr = sys::getProcessTriple();
+ PageSize = sys::Process::getPageSizeEstimate();
+
+ EP.template addHandler<orcrpctpc::GetTargetTriple>(*this,
+ &ThisT::getTargetTriple);
+ EP.template addHandler<orcrpctpc::GetPageSize>(*this, &ThisT::getPageSize);
+
+ EP.template addHandler<orcrpctpc::ReserveMem>(*this, &ThisT::reserveMemory);
+ EP.template addHandler<orcrpctpc::FinalizeMem>(*this,
+ &ThisT::finalizeMemory);
+ EP.template addHandler<orcrpctpc::ReleaseMem>(*this, &ThisT::releaseMemory);
+
+ EP.template addHandler<orcrpctpc::WriteUInt8s>(
+ handleWriteUInt<tpctypes::UInt8Write>);
+ EP.template addHandler<orcrpctpc::WriteUInt16s>(
+ handleWriteUInt<tpctypes::UInt16Write>);
+ EP.template addHandler<orcrpctpc::WriteUInt32s>(
+ handleWriteUInt<tpctypes::UInt32Write>);
+ EP.template addHandler<orcrpctpc::WriteUInt64s>(
+ handleWriteUInt<tpctypes::UInt64Write>);
+ EP.template addHandler<orcrpctpc::WriteBuffers>(handleWriteBuffer);
+
+ EP.template addHandler<orcrpctpc::LoadDylib>(*this, &ThisT::loadDylib);
+ EP.template addHandler<orcrpctpc::LookupSymbols>(*this,
+ &ThisT::lookupSymbols);
+
+ EP.template addHandler<orcrpctpc::RunMain>(*this, &ThisT::runMain);
+ EP.template addHandler<orcrpctpc::RunWrapper>(*this, &ThisT::runWrapper);
+
+ EP.template addHandler<orcrpctpc::CloseConnection>(*this,
+ &ThisT::closeConnection);
+ }
+
+ /// Set the ProgramName to be used as the first argv element when running
+ /// functions via runAsMain.
+ void setProgramName(Optional<std::string> ProgramName = None) {
+ this->ProgramName = std::move(ProgramName);
+ }
+
+ /// Get the RPC endpoint for this server.
+ RPCEndpointT &getEndpoint() { return EP; }
+
+ /// Run the server loop.
+ Error run() {
+ while (!Finished) {
+ if (auto Err = EP.handleOne())
+ return Err;
+ }
+ return Error::success();
+ }
+
+private:
+ std::string getTargetTriple() { return TripleStr; }
+ uint64_t getPageSize() { return PageSize; }
+
+ template <typename WriteT>
+ static void handleWriteUInt(const std::vector<WriteT> &Ws) {
+ using ValueT = decltype(std::declval<WriteT>().Value);
+ for (auto &W : Ws)
+ *jitTargetAddressToPointer<ValueT *>(W.Address) = W.Value;
+ }
+
+ std::string getProtStr(orcrpctpc::WireProtectionFlags WPF) {
+ std::string Result;
+ Result += (WPF & orcrpctpc::WPF_Read) ? 'R' : '-';
+ Result += (WPF & orcrpctpc::WPF_Write) ? 'W' : '-';
+ Result += (WPF & orcrpctpc::WPF_Exec) ? 'X' : '-';
+ return Result;
+ }
+
+ static void handleWriteBuffer(const std::vector<tpctypes::BufferWrite> &Ws) {
+ for (auto &W : Ws) {
+ memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
+ W.Buffer.size());
+ }
+ }
+
+ Expected<orcrpctpc::ReserveMemResult>
+ reserveMemory(const orcrpctpc::ReserveMemRequest &Request) {
+ orcrpctpc::ReserveMemResult Allocs;
+ auto PF = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
+
+ uint64_t TotalSize = 0;
+
+ for (const auto &E : Request) {
+ uint64_t Size = alignTo(E.Size, PageSize);
+ uint16_t Align = E.Alignment;
+
+ if ((Align > PageSize) || (PageSize % Align))
+ return make_error<StringError>(
+ "Page alignmen does not satisfy requested alignment",
+ inconvertibleErrorCode());
+
+ TotalSize += Size;
+ }
+
+ // Allocate memory slab.
+ std::error_code EC;
+ auto MB = sys::Memory::allocateMappedMemory(TotalSize, nullptr, PF, EC);
+ if (EC)
+ return make_error<StringError>("Unable to allocate memory: " +
+ EC.message(),
+ inconvertibleErrorCode());
+
+ // Zero-fill the whole thing.
+ memset(MB.base(), 0, MB.allocatedSize());
+
+ // Carve up sections to return.
+ uint64_t SectionBase = 0;
+ for (const auto &E : Request) {
+ uint64_t SectionSize = alignTo(E.Size, PageSize);
+ Allocs.push_back({E.Prot,
+ pointerToJITTargetAddress(MB.base()) + SectionBase,
+ SectionSize});
+ SectionBase += SectionSize;
+ }
+
+ return Allocs;
+ }
+
+ Error finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &FMR) {
+ for (const auto &E : FMR) {
+ sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
+
+ auto PF = orcrpctpc::fromWireProtectionFlags(E.Prot);
+ if (auto EC =
+ sys::Memory::protectMappedMemory(MB, static_cast<unsigned>(PF)))
+ return make_error<StringError>("error protecting memory: " +
+ EC.message(),
+ inconvertibleErrorCode());
+ }
+ return Error::success();
+ }
+
+ Error releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &RMR) {
+ for (const auto &E : RMR) {
+ sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
+
+ if (auto EC = sys::Memory::releaseMappedMemory(MB))
+ return make_error<StringError>("error release memory: " + EC.message(),
+ inconvertibleErrorCode());
+ }
+ return Error::success();
+ }
+
+ Expected<tpctypes::DylibHandle> loadDylib(const std::string &Path) {
+ std::string ErrMsg;
+ const char *DLPath = !Path.empty() ? Path.c_str() : nullptr;
+ auto DL = sys::DynamicLibrary::getPermanentLibrary(DLPath, &ErrMsg);
+ if (!DL.isValid())
+ return make_error<StringError>(std::move(ErrMsg),
+ inconvertibleErrorCode());
+
+ tpctypes::DylibHandle H = Dylibs.size();
+ Dylibs[H] = std::move(DL);
+ return H;
+ }
+
+ Expected<std::vector<tpctypes::LookupResult>>
+ lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> &Request) {
+ std::vector<tpctypes::LookupResult> Result;
+
+ for (const auto &E : Request) {
+ auto I = Dylibs.find(E.first);
+ if (I == Dylibs.end())
+ return make_error<StringError>("Unrecognized handle",
+ inconvertibleErrorCode());
+ auto &DL = I->second;
+ Result.push_back({});
+
+ for (const auto &KV : E.second) {
+ auto &SymString = KV.first;
+ bool WeakReference = KV.second;
+
+ const char *Sym = SymString.c_str();
+#ifdef __APPLE__
+ if (*Sym == '_')
+ ++Sym;
+#endif
+
+ void *Addr = DL.getAddressOfSymbol(Sym);
+ if (!Addr && !WeakReference)
+ return make_error<StringError>(Twine("Missing definition for ") + Sym,
+ inconvertibleErrorCode());
+
+ Result.back().push_back(pointerToJITTargetAddress(Addr));
+ }
+ }
+
+ return Result;
+ }
+
+ int32_t runMain(JITTargetAddress MainFnAddr,
+ const std::vector<std::string> &Args) {
+ Optional<StringRef> ProgramNameOverride;
+ if (ProgramName)
+ ProgramNameOverride = *ProgramName;
+
+ return runAsMain(
+ jitTargetAddressToFunction<int (*)(int, char *[])>(MainFnAddr), Args,
+ ProgramNameOverride);
+ }
+
+ tpctypes::WrapperFunctionResult
+ runWrapper(JITTargetAddress WrapperFnAddr,
+ const std::vector<uint8_t> &ArgBuffer) {
+ using WrapperFnTy = tpctypes::CWrapperFunctionResult (*)(
+ const uint8_t *Data, uint64_t Size);
+ auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
+ return WrapperFn(ArgBuffer.data(), ArgBuffer.size());
+ }
+
+ void closeConnection() { Finished = true; }
+
+ std::string TripleStr;
+ uint64_t PageSize = 0;
+ Optional<std::string> ProgramName;
+ RPCEndpointT &EP;
+ std::atomic<bool> Finished{false};
+ DenseMap<tpctypes::DylibHandle, sys::DynamicLibrary> Dylibs;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h
new file mode 100644
index 0000000..811c50e
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h
@@ -0,0 +1,41 @@
+//===----- RegisterEHFrames.h -- Register EH frame sections -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Support for dynamically registering and deregistering eh-frame sections
+// in-process via libunwind.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H
+
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+#include "llvm/Support/Error.h"
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+/// Register frames in the given eh-frame section with libunwind.
+Error registerEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize);
+
+/// Unregister frames in the given eh-frame section with libunwind.
+Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize);
+
+} // end namespace orc
+} // end namespace llvm
+
+extern "C" llvm::orc::tpctypes::CWrapperFunctionResult
+llvm_orc_registerEHFrameSectionWrapper(uint8_t *Data, uint64_t Size);
+
+extern "C" llvm::orc::tpctypes::CWrapperFunctionResult
+llvm_orc_deregisterEHFrameSectionWrapper(uint8_t *Data, uint64_t Size);
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
new file mode 100644
index 0000000..1d2f6d2
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
@@ -0,0 +1,38 @@
+//===-- TargetExecutionUtils.h - Utils for execution in target --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for execution in the target process.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace llvm {
+namespace orc {
+
+/// Run a main function, returning the result.
+///
+/// If the optional ProgramName argument is given then it will be inserted
+/// before the strings in Args as the first argument to the called function.
+///
+/// It is legal to have an empty argument list and no program name, however
+/// many main functions will expect a name argument at least, and will fail
+/// if none is provided.
+int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
+ Optional<StringRef> ProgramName = None);
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
new file mode 100644
index 0000000..504a5ea
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
@@ -0,0 +1,210 @@
+//===--- TargetProcessControl.h - Target process control APIs ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for interacting with target processes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+
+#include <future>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+/// TargetProcessControl supports interaction with a JIT target process.
+class TargetProcessControl {
+public:
+ /// APIs for manipulating memory in the target process.
+ class MemoryAccess {
+ public:
+ /// Callback function for asynchronous writes.
+ using WriteResultFn = unique_function<void(Error)>;
+
+ virtual ~MemoryAccess();
+
+ virtual void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) = 0;
+
+ virtual void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
+ WriteResultFn OnWriteComplete) = 0;
+
+ virtual void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
+ WriteResultFn OnWriteComplete) = 0;
+
+ virtual void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
+ WriteResultFn OnWriteComplete) = 0;
+
+ virtual void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
+ WriteResultFn OnWriteComplete) = 0;
+
+ Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ writeUInt8s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
+ return ResultF.get();
+ }
+
+ Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ writeUInt16s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
+ return ResultF.get();
+ }
+
+ Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ writeUInt32s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
+ return ResultF.get();
+ }
+
+ Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ writeUInt64s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
+ return ResultF.get();
+ }
+
+ Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ writeBuffers(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
+ return ResultF.get();
+ }
+ };
+
+ virtual ~TargetProcessControl();
+
+ /// Intern a symbol name in the SymbolStringPool.
+ SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
+
+ /// Return a shared pointer to the SymbolStringPool for this instance.
+ std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
+
+ /// Return the Triple for the target process.
+ const Triple &getTargetTriple() const { return TargetTriple; }
+
+ /// Get the page size for the target process.
+ unsigned getPageSize() const { return PageSize; }
+
+ /// Return a MemoryAccess object for the target process.
+ MemoryAccess &getMemoryAccess() const { return *MemAccess; }
+
+ /// Return a JITLinkMemoryManager for the target process.
+ jitlink::JITLinkMemoryManager &getMemMgr() const { return *MemMgr; }
+
+ /// Load the dynamic library at the given path and return a handle to it.
+ /// If LibraryPath is null this function will return the global handle for
+ /// the target process.
+ virtual Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) = 0;
+
+ /// Search for symbols in the target process.
+ ///
+ /// The result of the lookup is a 2-dimentional array of target addresses
+ /// that correspond to the lookup order. If a required symbol is not
+ /// found then this method will return an error. If a weakly referenced
+ /// symbol is not found then it be assigned a '0' value in the result.
+ /// that correspond to the lookup order.
+ virtual Expected<std::vector<tpctypes::LookupResult>>
+ lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) = 0;
+
+ /// Run function with a main-like signature.
+ virtual Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
+ ArrayRef<std::string> Args) = 0;
+
+ /// Run a wrapper function with signature:
+ ///
+ /// \code{.cpp}
+ /// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
+ /// \endcode{.cpp}
+ ///
+ virtual Expected<tpctypes::WrapperFunctionResult>
+ runWrapper(JITTargetAddress WrapperFnAddr, ArrayRef<uint8_t> ArgBuffer) = 0;
+
+ /// Disconnect from the target process.
+ ///
+ /// This should be called after the JIT session is shut down.
+ virtual Error disconnect() = 0;
+
+protected:
+ TargetProcessControl(std::shared_ptr<SymbolStringPool> SSP)
+ : SSP(std::move(SSP)) {}
+
+ std::shared_ptr<SymbolStringPool> SSP;
+ Triple TargetTriple;
+ unsigned PageSize = 0;
+ MemoryAccess *MemAccess = nullptr;
+ jitlink::JITLinkMemoryManager *MemMgr = nullptr;
+};
+
+/// A TargetProcessControl implementation targeting the current process.
+class SelfTargetProcessControl : public TargetProcessControl,
+ private TargetProcessControl::MemoryAccess {
+public:
+ SelfTargetProcessControl(
+ std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
+ unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
+
+ /// Create a SelfTargetProcessControl with the given memory manager.
+ /// If no memory manager is given a jitlink::InProcessMemoryManager will
+ /// be used by default.
+ static Expected<std::unique_ptr<SelfTargetProcessControl>>
+ Create(std::shared_ptr<SymbolStringPool> SSP,
+ std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr);
+
+ Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
+
+ Expected<std::vector<tpctypes::LookupResult>>
+ lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) override;
+
+ Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
+ ArrayRef<std::string> Args) override;
+
+ Expected<tpctypes::WrapperFunctionResult>
+ runWrapper(JITTargetAddress WrapperFnAddr,
+ ArrayRef<uint8_t> ArgBuffer) override;
+
+ Error disconnect() override;
+
+private:
+ void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
+ WriteResultFn OnWriteComplete) override;
+
+ std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
+ char GlobalManglingPrefix = 0;
+ std::vector<std::unique_ptr<sys::DynamicLibrary>> DynamicLibraries;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
index 5787500..82f2b74 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
@@ -38,17 +38,12 @@
public:
// RAII based lock for ThreadSafeContext.
class LLVM_NODISCARD Lock {
- private:
- using UnderlyingLock = std::lock_guard<std::recursive_mutex>;
-
public:
- Lock(std::shared_ptr<State> S)
- : S(std::move(S)),
- L(llvm::make_unique<UnderlyingLock>(this->S->Mutex)) {}
+ Lock(std::shared_ptr<State> S) : S(std::move(S)), L(this->S->Mutex) {}
private:
std::shared_ptr<State> S;
- std::unique_ptr<UnderlyingLock> L;
+ std::unique_lock<std::recursive_mutex> L;
};
/// Construct a null context.
@@ -69,7 +64,7 @@
/// instance, or null if the instance was default constructed.
const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; }
- Lock getLock() {
+ Lock getLock() const {
assert(S && "Can not lock an empty ThreadSafeContext");
return Lock(S);
}
@@ -95,7 +90,7 @@
// We also need to lock the context to make sure the module tear-down
// does not overlap any other work on the context.
if (M) {
- auto L = getContextLock();
+ auto L = TSCtx.getLock();
M = nullptr;
}
M = std::move(Other.M);
@@ -117,23 +112,14 @@
~ThreadSafeModule() {
// We need to lock the context while we destruct the module.
if (M) {
- auto L = getContextLock();
+ auto L = TSCtx.getLock();
M = nullptr;
}
}
- /// Get the module wrapped by this ThreadSafeModule.
- Module *getModule() { return M.get(); }
-
- /// Get the module wrapped by this ThreadSafeModule.
- const Module *getModule() const { return M.get(); }
-
- /// Take out a lock on the ThreadSafeContext for this module.
- ThreadSafeContext::Lock getContextLock() { return TSCtx.getLock(); }
-
/// Boolean conversion: This ThreadSafeModule will evaluate to true if it
/// wraps a non-null module.
- explicit operator bool() {
+ explicit operator bool() const {
if (M) {
assert(TSCtx.getContext() &&
"Non-null module must have non-null context");
@@ -142,6 +128,30 @@
return false;
}
+ /// Locks the associated ThreadSafeContext and calls the given function
+ /// on the contained Module.
+ template <typename Func> decltype(auto) withModuleDo(Func &&F) {
+ assert(M && "Can not call on null module");
+ auto Lock = TSCtx.getLock();
+ return F(*M);
+ }
+
+ /// Locks the associated ThreadSafeContext and calls the given function
+ /// on the contained Module.
+ template <typename Func> decltype(auto) withModuleDo(Func &&F) const {
+ auto Lock = TSCtx.getLock();
+ return F(*M);
+ }
+
+ /// Get a raw pointer to the contained module without locking the context.
+ Module *getModuleUnlocked() { return M.get(); }
+
+ /// Get a raw pointer to the contained module without locking the context.
+ const Module *getModuleUnlocked() const { return M.get(); }
+
+ /// Returns the context for this ThreadSafeModule.
+ ThreadSafeContext getContext() const { return TSCtx; }
+
private:
std::unique_ptr<Module> M;
ThreadSafeContext TSCtx;
@@ -152,7 +162,7 @@
/// Clones the given module on to a new context.
ThreadSafeModule
-cloneToNewContext(ThreadSafeModule &TSMW,
+cloneToNewContext(const ThreadSafeModule &TSMW,
GVPredicate ShouldCloneDef = GVPredicate(),
GVModifier UpdateClonedDefSource = GVModifier());