#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
-//#include "CloneSubModule.h"
#include "IndirectionUtils.h"
#include "LambdaResolver.h"
+#include "LogicalDylib.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/Transforms/Utils/Cloning.h"
/// 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>
+template <typename BaseLayerT,
+ typename CompileCallbackMgrT = JITCompileCallbackManagerBase,
+ typename IndirectStubsMgrT = IndirectStubsManagerBase>
class CompileOnDemandLayer {
private:
- // Utility class for MapValue. Only materializes declarations for global
- // variables.
- class GlobalDeclMaterializer : public ValueMaterializer {
+ template <typename MaterializerFtor>
+ class LambdaMaterializer : public ValueMaterializer {
public:
- GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {}
+ LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
Value* materializeValueFor(Value *V) final {
- if (auto *GV = dyn_cast<GlobalVariable>(V))
- return cloneGlobalVariableDecl(Dst, *GV);
- else if (auto *F = dyn_cast<Function>(V))
- return cloneFunctionDecl(Dst, *F);
- // Else.
- return nullptr;
+ return M(V);
}
private:
- Module &Dst;
+ MaterializerFtor M;
};
- typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
- class UncompiledPartition;
-
- // Logical module.
- //
- // This struct contains the handles for the global values and stubs (which
- // cover the external symbols of the original module), plus the handes for
- // each of the extracted partitions. These handleds are used for lookup (only
- // the globals/stubs module is searched) and memory management. The actual
- // searching and resource management are handled by the LogicalDylib that owns
- // the LogicalModule.
- struct LogicalModule {
- LogicalModule() {}
-
- LogicalModule(LogicalModule &&Other)
- : SrcM(std::move(Other.SrcM)),
- GVsAndStubsHandle(std::move(Other.GVsAndStubsHandle)),
- ImplHandles(std::move(Other.ImplHandles)) {}
-
- std::unique_ptr<Module> SrcM;
- BaseLayerModuleSetHandleT GVsAndStubsHandle;
- std::vector<BaseLayerModuleSetHandleT> ImplHandles;
- };
-
- // Logical dylib.
- //
- // This class handles symbol resolution and resource management for a set of
- // modules that were added together as a logical dylib.
- //
- // A logical dylib contains one-or-more LogicalModules plus a set of
- // UncompiledPartitions. LogicalModules support symbol resolution and resource
- // management for for code that has already been emitted. UncompiledPartitions
- // represent code that has not yet been compiled.
- class LogicalDylib {
- private:
- friend class UncompiledPartition;
- typedef std::list<LogicalModule> LogicalModuleList;
- public:
-
- typedef unsigned UncompiledPartitionID;
- typedef typename LogicalModuleList::iterator LMHandle;
-
- // Construct a logical dylib.
- LogicalDylib(CompileOnDemandLayer &CODLayer) : CODLayer(CODLayer) { }
-
- // Delete this logical dylib, release logical module resources.
- virtual ~LogicalDylib() {
- releaseLogicalModuleResources();
- }
-
- // Get a reference to the containing layer.
- CompileOnDemandLayer& getCODLayer() { return CODLayer; }
-
- // Get a reference to the base layer.
- BaseLayerT& getBaseLayer() { return CODLayer.BaseLayer; }
-
- // Start a new context for a single logical module.
- LMHandle createLogicalModule() {
- LogicalModules.push_back(LogicalModule());
- return std::prev(LogicalModules.end());
- }
-
- // Set the global-values-and-stubs module handle for this logical module.
- void setGVsAndStubsHandle(LMHandle LMH, BaseLayerModuleSetHandleT H) {
- LMH->GVsAndStubsHandle = H;
- }
-
- // Return the global-values-and-stubs module handle for this logical module.
- BaseLayerModuleSetHandleT getGVsAndStubsHandle(LMHandle LMH) {
- return LMH->GVsAndStubsHandle;
- }
-
- // Add a handle to a module containing lazy function bodies to the given
- // logical module.
- void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
- LMH->ImplHandles.push_back(H);
- }
-
- // Create an UncompiledPartition attached to this LogicalDylib.
- UncompiledPartition& createUncompiledPartition(LMHandle LMH,
- std::shared_ptr<Module> SrcM);
-
- // Take ownership of the given UncompiledPartition from the logical dylib.
- std::unique_ptr<UncompiledPartition>
- takeUPOwnership(UncompiledPartitionID ID);
-
- // Look up a symbol in this context.
- JITSymbol findSymbolInternally(LMHandle LMH, const std::string &Name) {
- if (auto Symbol = getBaseLayer().findSymbolIn(LMH->GVsAndStubsHandle,
- Name, false))
- return Symbol;
-
- for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
- ++I)
- if (I != LMH)
- if (auto Symbol = getBaseLayer().findSymbolIn(I->GVsAndStubsHandle,
- Name, false))
- return Symbol;
-
- return nullptr;
- }
+ template <typename MaterializerFtor>
+ LambdaMaterializer<MaterializerFtor>
+ createLambdaMaterializer(MaterializerFtor M) {
+ return LambdaMaterializer<MaterializerFtor>(std::move(M));
+ }
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- for (auto &LM : LogicalModules)
- if (auto Symbol = getBaseLayer().findSymbolIn(LM.GVsAndStubsHandle,
- Name,
- ExportedSymbolsOnly))
- return Symbol;
- return nullptr;
- }
+ typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
- // Find an external symbol (via the user supplied SymbolResolver).
- virtual RuntimeDyld::SymbolInfo
- findSymbolExternally(const std::string &Name) const = 0;
+ struct LogicalModuleResources {
+ std::shared_ptr<Module> SourceModule;
+ std::set<const Function*> StubsToClone;
+ std::unique_ptr<IndirectStubsMgrT> StubsMgr;
- private:
-
- void releaseLogicalModuleResources() {
- for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
- ++I) {
- getBaseLayer().removeModuleSet(I->GVsAndStubsHandle);
- for (auto H : I->ImplHandles)
- getBaseLayer().removeModuleSet(H);
+ JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ if (Name.endswith("$stub_ptr") && !ExportedSymbolsOnly) {
+ assert(!ExportedSymbolsOnly && "Stubs are never exported");
+ return StubsMgr->findPointer(Name.drop_back(9));
}
+ return StubsMgr->findStub(Name, ExportedSymbolsOnly);
}
- CompileOnDemandLayer &CODLayer;
- LogicalModuleList LogicalModules;
- std::vector<std::unique_ptr<UncompiledPartition>> UncompiledPartitions;
};
- template <typename ResolverPtrT>
- class LogicalDylibImpl : public LogicalDylib {
- public:
- LogicalDylibImpl(CompileOnDemandLayer &CODLayer, ResolverPtrT Resolver)
- : LogicalDylib(CODLayer), Resolver(std::move(Resolver)) {}
-
- RuntimeDyld::SymbolInfo
- findSymbolExternally(const std::string &Name) const override {
- return Resolver->findSymbol(Name);
- }
-
- private:
- ResolverPtrT Resolver;
+ struct LogicalDylibResources {
+ typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
+ SymbolResolverFtor;
+ SymbolResolverFtor ExternalSymbolResolver;
};
- template <typename ResolverPtrT>
- static std::unique_ptr<LogicalDylib>
- createLogicalDylib(CompileOnDemandLayer &CODLayer,
- ResolverPtrT Resolver) {
- typedef LogicalDylibImpl<ResolverPtrT> Impl;
- return llvm::make_unique<Impl>(CODLayer, std::move(Resolver));
- }
-
- // Uncompiled partition.
- //
- // Represents one as-yet uncompiled portion of a module.
- class UncompiledPartition {
- public:
-
- struct PartitionEntry {
- PartitionEntry(Function *F, TargetAddress CallbackID)
- : F(F), CallbackID(CallbackID) {}
- Function *F;
- TargetAddress CallbackID;
- };
-
- typedef std::vector<PartitionEntry> PartitionEntryList;
-
- // Creates an uncompiled partition with the list of functions that make up
- // this partition.
- UncompiledPartition(LogicalDylib &LD, typename LogicalDylib::LMHandle LMH,
- std::shared_ptr<Module> SrcM)
- : LD(LD), LMH(LMH), SrcM(std::move(SrcM)), ID(~0U) {}
-
- ~UncompiledPartition() {
- // FIXME: When we want to support threaded lazy compilation we'll need to
- // lock the callback manager here.
- auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
- for (auto PEntry : PartitionEntries)
- CCMgr.releaseCompileCallback(PEntry.CallbackID);
- }
-
- // Set the ID for this partition.
- void setID(typename LogicalDylib::UncompiledPartitionID ID) {
- this->ID = ID;
- }
-
- // Set the function set and callbacks for this partition.
- void setPartitionEntries(PartitionEntryList PartitionEntries) {
- this->PartitionEntries = std::move(PartitionEntries);
- }
-
- // Handle a compile callback for the function at index FnIdx.
- TargetAddress compile(unsigned FnIdx) {
- // Take ownership of self. This will ensure we delete the partition and
- // free all its resources once we're done compiling.
- std::unique_ptr<UncompiledPartition> This = LD.takeUPOwnership(ID);
-
- // Release all other compile callbacks for this partition.
- // We skip the callback for this function because that's the one that
- // called us, and the callback manager will already have removed it.
- auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
- for (unsigned I = 0; I < PartitionEntries.size(); ++I)
- if (I != FnIdx)
- CCMgr.releaseCompileCallback(PartitionEntries[I].CallbackID);
-
- // Grab the name of the function being called here.
- Function *F = PartitionEntries[FnIdx].F;
- std::string CalledFnName = Mangle(F->getName(), SrcM->getDataLayout());
-
- // Extract the function and add it to the base layer.
- auto PartitionImplH = emitPartition();
- LD.addToLogicalModule(LMH, PartitionImplH);
-
- // Update body pointers.
- // FIXME: When we start supporting remote lazy jitting this will need to
- // be replaced with a user-supplied callback for updating the
- // remote pointers.
- TargetAddress CalledAddr = 0;
- for (unsigned I = 0; I < PartitionEntries.size(); ++I) {
- auto F = PartitionEntries[I].F;
- std::string FName(F->getName());
- auto FnBodySym =
- LD.getBaseLayer().findSymbolIn(PartitionImplH,
- Mangle(FName, SrcM->getDataLayout()),
- false);
- auto FnPtrSym =
- LD.getBaseLayer().findSymbolIn(LD.getGVsAndStubsHandle(LMH),
- Mangle(FName + "$orc_addr",
- SrcM->getDataLayout()),
- false);
- assert(FnBodySym && "Couldn't find function body.");
- assert(FnPtrSym && "Couldn't find function body pointer.");
-
- auto FnBodyAddr = FnBodySym.getAddress();
- void *FnPtrAddr = reinterpret_cast<void*>(
- static_cast<uintptr_t>(FnPtrSym.getAddress()));
-
- // If this is the function we're calling record the address so we can
- // return it from this function.
- if (I == FnIdx)
- CalledAddr = FnBodyAddr;
-
- memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
- }
-
- // Finally, clear the partition structure so we don't try to
- // double-release the callbacks in the UncompiledPartition destructor.
- PartitionEntries.clear();
-
- return CalledAddr;
- }
-
- private:
-
- BaseLayerModuleSetHandleT emitPartition() {
- // Create the module.
- std::string NewName(SrcM->getName());
- for (auto &PEntry : PartitionEntries) {
- NewName += ".";
- NewName += PEntry.F->getName();
- }
- auto PM = llvm::make_unique<Module>(NewName, SrcM->getContext());
- PM->setDataLayout(SrcM->getDataLayout());
- ValueToValueMapTy VMap;
- GlobalDeclMaterializer GDM(*PM);
-
- // Create decls in the new module.
- for (auto &PEntry : PartitionEntries)
- cloneFunctionDecl(*PM, *PEntry.F, &VMap);
-
- // Move the function bodies.
- for (auto &PEntry : PartitionEntries)
- moveFunctionBody(*PEntry.F, VMap);
-
- // Create memory manager and symbol resolver.
- auto MemMgr = llvm::make_unique<SectionMemoryManager>();
- auto Resolver = createLambdaResolver(
- [this](const std::string &Name) {
- if (auto Symbol = LD.findSymbolInternally(LMH, Name))
- return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
- Symbol.getFlags());
- return LD.findSymbolExternally(Name);
- },
- [this](const std::string &Name) {
- if (auto Symbol = LD.findSymbolInternally(LMH, Name))
- return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
- Symbol.getFlags());
- return RuntimeDyld::SymbolInfo(nullptr);
- });
- std::vector<std::unique_ptr<Module>> PartMSet;
- PartMSet.push_back(std::move(PM));
- return LD.getBaseLayer().addModuleSet(std::move(PartMSet),
- std::move(MemMgr),
- std::move(Resolver));
- }
+ typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
+ LogicalDylibResources> CODLogicalDylib;
- LogicalDylib &LD;
- typename LogicalDylib::LMHandle LMH;
- std::shared_ptr<Module> SrcM;
- typename LogicalDylib::UncompiledPartitionID ID;
- PartitionEntryList PartitionEntries;
- };
-
- typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList;
+ typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
+ typedef std::list<CODLogicalDylib> LogicalDylibList;
public:
+
/// @brief Handle to a set of loaded modules.
typedef typename LogicalDylibList::iterator ModuleSetHandleT;
+ /// @brief Module partitioning functor.
+ typedef std::function<std::set<Function*>(Function&)> PartitioningFtor;
+
+ /// @brief Builder for IndirectStubsManagers.
+ typedef std::function<std::unique_ptr<IndirectStubsMgrT>()>
+ IndirectStubsManagerBuilderT;
+
/// @brief Construct a compile-on-demand layer instance.
- CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
- : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {}
+ CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
+ CompileCallbackMgrT &CallbackMgr,
+ IndirectStubsManagerBuilderT CreateIndirectStubsManager,
+ bool CloneStubsIntoPartitions = true)
+ : BaseLayer(BaseLayer), Partition(Partition),
+ CompileCallbackMgr(CallbackMgr),
+ CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
+ CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
/// @brief Add a module to the compile-on-demand layer.
template <typename ModuleSetT, typename MemoryManagerPtrT,
assert(MemMgr == nullptr &&
"User supplied memory managers not supported with COD yet.");
- LogicalDylibs.push_back(createLogicalDylib(*this, std::move(Resolver)));
+ LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
+ auto &LDResources = LogicalDylibs.back().getDylibResources();
+
+ LDResources.ExternalSymbolResolver =
+ [Resolver](const std::string &Name) {
+ return Resolver->findSymbol(Name);
+ };
// Process each of the modules in this module set.
- for (auto &M : Ms) {
- std::vector<std::vector<Function*>> Partitioning;
- for (auto &F : *M) {
- if (F.isDeclaration())
- continue;
- Partitioning.push_back(std::vector<Function*>());
- Partitioning.back().push_back(&F);
- }
- addLogicalModule(*LogicalDylibs.back(),
- std::shared_ptr<Module>(std::move(M)),
- std::move(Partitioning));
- }
+ for (auto &M : Ms)
+ addLogicalModule(LogicalDylibs.back(),
+ std::shared_ptr<Module>(std::move(M)));
return std::prev(LogicalDylibs.end());
}
/// @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) {
- return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
+ for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
+ LDI != LDE; ++LDI)
+ if (auto Symbol = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
+ return Symbol;
+ return nullptr;
}
/// @brief Get the address of a symbol provided by this layer, or some layer
/// below this one.
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
- return (*H)->findSymbol(Name, ExportedSymbolsOnly);
+ return H->findSymbol(Name, ExportedSymbolsOnly);
}
private:
- void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcM,
- std::vector<std::vector<Function*>> Partitions) {
+ void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module> SrcM) {
// Bump the linkage and rename any anonymous/privote members in SrcM to
// ensure that everything will resolve properly after we partition SrcM.
// Create a logical module handle for SrcM within the logical dylib.
auto LMH = LD.createLogicalModule();
+ auto &LMResources = LD.getLogicalModuleResources(LMH);
+
+ LMResources.SourceModule = SrcM;
+
+ // Create the GlobalValues module.
+ const DataLayout &DL = SrcM->getDataLayout();
+ auto GVsM = llvm::make_unique<Module>((SrcM->getName() + ".globals").str(),
+ SrcM->getContext());
+ GVsM->setDataLayout(DL);
- // Create the GVs-and-stubs module.
- auto GVsAndStubsM = llvm::make_unique<Module>(
- (SrcM->getName() + ".globals_and_stubs").str(),
- SrcM->getContext());
- GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
+ // Create function stubs.
ValueToValueMapTy VMap;
+ {
+ typename IndirectStubsMgrT::StubInitsMap StubInits;
+ for (auto &F : *SrcM) {
+ // Skip declarations.
+ if (F.isDeclaration())
+ continue;
- // Process partitions and create stubs.
- // We create the stubs before copying the global variables as we know the
- // stubs won't refer to any globals (they only refer to their implementation
- // pointer) so there's no ordering/value-mapping issues.
- for (auto& Partition : Partitions) {
- auto &UP = LD.createUncompiledPartition(LMH, SrcM);
- typename UncompiledPartition::PartitionEntryList PartitionEntries;
- for (auto &F : Partition) {
- assert(!F->isDeclaration() &&
- "Partition should only contain definitions");
- unsigned FnIdx = PartitionEntries.size();
- auto CCI = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
- PartitionEntries.push_back(
- typename UncompiledPartition::PartitionEntry(F, CCI.getAddress()));
- Function *StubF = cloneFunctionDecl(*GVsAndStubsM, *F, &VMap);
- GlobalVariable *FnBodyPtr =
- createImplPointer(*StubF->getType(), *StubF->getParent(),
- StubF->getName() + "$orc_addr",
- createIRTypedAddress(*StubF->getFunctionType(),
- CCI.getAddress()));
- makeStub(*StubF, *FnBodyPtr);
- CCI.setCompileAction([&UP, FnIdx]() { return UP.compile(FnIdx); });
+ // Record all functions defined by this module.
+ if (CloneStubsIntoPartitions)
+ LMResources.StubsToClone.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 CCInfo = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
+ StubInits[mangle(F.getName(), DL)] =
+ std::make_pair(CCInfo.getAddress(),
+ JITSymbolBase::flagsFromGlobalValue(F));
+ CCInfo.setCompileAction(
+ [this, &LD, LMH, &F]() {
+ return this->extractAndCompile(LD, LMH, F);
+ });
}
- UP.setPartitionEntries(std::move(PartitionEntries));
+ LMResources.StubsMgr = CreateIndirectStubsManager();
+ auto EC = LMResources.StubsMgr->init(StubInits);
+ (void)EC;
+ // FIXME: This should be propagated back to the user. Stub creation may
+ // fail for remote JITs.
+ assert(!EC && "Error generating stubs");
}
- // Now clone the global variable declarations.
- GlobalDeclMaterializer GDMat(*GVsAndStubsM);
+ // Clone global variable decls.
for (auto &GV : SrcM->globals())
- if (!GV.isDeclaration())
- cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
-
- // Then clone the initializers.
+ 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);
+
+ // 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(
+ [&GVsM, &LMResources](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);
+ auto StubSym = LMResources.StubsMgr->findStub(FName, false);
+ unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
+ ConstantInt *StubAddr =
+ ConstantInt::get(GVsM->getContext(),
+ APInt(PtrBitWidth, StubSym.getAddress()));
+ Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
+ StubAddr, 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, &GDMat);
+ 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 stubs module and add it to the base layer.
- auto GVsAndStubsResolver = createLambdaResolver(
- [&LD](const std::string &Name) {
- if (auto Symbol = LD.findSymbol(Name, false))
- return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
- Symbol.getFlags());
- return LD.findSymbolExternally(Name);
+ // Build a resolver for the globals module and add it to the base layer.
+ auto GVsResolver = createLambdaResolver(
+ [&LD, LMH](const std::string &Name) {
+ auto &LMResources = LD.getLogicalModuleResources(LMH);
+ if (auto Sym = LMResources.StubsMgr->findStub(Name, false))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
+ return LD.getDylibResources().ExternalSymbolResolver(Name);
},
- [&LD](const std::string &Name) {
+ [](const std::string &Name) {
return RuntimeDyld::SymbolInfo(nullptr);
});
- std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
- GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
- auto GVsAndStubsH =
- BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
+ std::vector<std::unique_ptr<Module>> GVsMSet;
+ GVsMSet.push_back(std::move(GVsM));
+ auto GVsH =
+ BaseLayer.addModuleSet(std::move(GVsMSet),
llvm::make_unique<SectionMemoryManager>(),
- std::move(GVsAndStubsResolver));
- LD.setGVsAndStubsHandle(LMH, GVsAndStubsH);
+ std::move(GVsResolver));
+ LD.addToLogicalModule(LMH, GVsH);
}
- static std::string Mangle(StringRef Name, const DataLayout &DL) {
- Mangler M(&DL);
+ static std::string mangle(StringRef Name, const DataLayout &DL) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
- M.getNameWithPrefix(MangledNameStream, Name);
+ Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
+ TargetAddress extractAndCompile(CODLogicalDylib &LD,
+ LogicalModuleHandle LMH,
+ Function &F) {
+ auto &LMResources = LD.getLogicalModuleResources(LMH);
+ Module &SrcM = *LMResources.SourceModule;
+
+ // 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());
+
+ auto Part = Partition(F);
+ auto PartH = emitPartition(LD, LMH, Part);
+
+ TargetAddress CalledAddr = 0;
+ for (auto *SubF : Part) {
+ std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
+ auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
+ assert(FnBodySym && "Couldn't find function body.");
+
+ TargetAddress FnBodyAddr = FnBodySym.getAddress();
+
+ // 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 = LMResources.StubsMgr->updatePointer(FnName, FnBodyAddr))
+ return 0;
+ }
+
+ return CalledAddr;
+ }
+
+ template <typename PartitionT>
+ BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
+ LogicalModuleHandle LMH,
+ const PartitionT &Part) {
+ auto &LMResources = LD.getLogicalModuleResources(LMH);
+ Module &SrcM = *LMResources.SourceModule;
+
+ // 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(
+ [this, &LMResources, &M, &VMap](Value *V) -> Value* {
+ if (auto *GV = dyn_cast<GlobalVariable>(V)) {
+ return cloneGlobalVariableDecl(*M, *GV);
+ } else if (auto *F = dyn_cast<Function>(V)) {
+ // Check whether we want to clone an available_externally definition.
+ if (LMResources.StubsToClone.count(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;
+ }
+
+ return cloneFunctionDecl(*M, *F);
+ } else if (auto *A = dyn_cast<GlobalAlias>(V)) {
+ auto *PTy = cast<PointerType>(A->getType());
+ if (PTy->getElementType()->isFunctionTy())
+ return Function::Create(cast<FunctionType>(PTy->getElementType()),
+ GlobalValue::ExternalLinkage,
+ A->getName(), M.get());
+ // else
+ return new GlobalVariable(*M, PTy->getElementType(), false,
+ GlobalValue::ExternalLinkage,
+ nullptr, A->getName(), nullptr,
+ GlobalValue::NotThreadLocal,
+ PTy->getAddressSpace());
+ }
+ // Else.
+ 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);
+
+ // Create memory manager and symbol resolver.
+ auto MemMgr = llvm::make_unique<SectionMemoryManager>();
+ auto Resolver = createLambdaResolver(
+ [this, &LD, LMH](const std::string &Name) {
+ if (auto Symbol = LD.findSymbolInternally(LMH, Name))
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return LD.getDylibResources().ExternalSymbolResolver(Name);
+ },
+ [this, &LD, LMH](const std::string &Name) {
+ if (auto Symbol = LD.findSymbolInternally(LMH, Name))
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return RuntimeDyld::SymbolInfo(nullptr);
+ });
+ std::vector<std::unique_ptr<Module>> PartMSet;
+ PartMSet.push_back(std::move(M));
+ return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
+ std::move(Resolver));
+ }
+
BaseLayerT &BaseLayer;
+ PartitioningFtor Partition;
CompileCallbackMgrT &CompileCallbackMgr;
+ IndirectStubsManagerBuilderT CreateIndirectStubsManager;
+
LogicalDylibList LogicalDylibs;
+ bool CloneStubsIntoPartitions;
};
-template <typename BaseLayerT, typename CompileCallbackMgrT>
-typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
- UncompiledPartition&
-CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
- createUncompiledPartition(LMHandle LMH, std::shared_ptr<Module> SrcM) {
- UncompiledPartitions.push_back(
- llvm::make_unique<UncompiledPartition>(*this, LMH, std::move(SrcM)));
- UncompiledPartitions.back()->setID(UncompiledPartitions.size() - 1);
- return *UncompiledPartitions.back();
-}
-
-template <typename BaseLayerT, typename CompileCallbackMgrT>
-std::unique_ptr<typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
- UncompiledPartition>
-CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
- takeUPOwnership(UncompiledPartitionID ID) {
-
- std::swap(UncompiledPartitions[ID], UncompiledPartitions.back());
- UncompiledPartitions[ID]->setID(ID);
- auto UP = std::move(UncompiledPartitions.back());
- UncompiledPartitions.pop_back();
- return UP;
-}
-
} // End namespace orc.
} // End namespace llvm.