[llvm] r236465 - [Orc] Refactor the compile-on-demand layer to make module partitioning lazy,
Lang Hames
lhames at gmail.com
Mon May 4 15:03:10 PDT 2015
Author: lhames
Date: Mon May 4 17:03:10 2015
New Revision: 236465
URL: http://llvm.org/viewvc/llvm-project?rev=236465&view=rev
Log:
[Orc] Refactor the compile-on-demand layer to make module partitioning lazy,
and avoid cloning unused decls into every partition.
Module partitioning showed up as a source of significant overhead when I
profiled some trivial test cases. Avoiding the overhead of partitionging
for uncalled functions helps to mitigate this.
This change also means that it is no longer necessary to have a
LazyEmittingLayer underneath the CompileOnDemand layer, since the
CompileOnDemandLayer will not extract or emit function bodies until they are
called.
Removed:
llvm/trunk/include/llvm/ExecutionEngine/Orc/CloneSubModule.h
llvm/trunk/lib/ExecutionEngine/Orc/CloneSubModule.cpp
Modified:
llvm/trunk/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp
llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
llvm/trunk/lib/ExecutionEngine/Orc/CMakeLists.txt
llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
llvm/trunk/test/ExecutionEngine/OrcLazy/hello.ll
llvm/trunk/tools/lli/OrcLazyJIT.h
Modified: llvm/trunk/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp (original)
+++ llvm/trunk/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp Mon May 4 17:03:10 2015
@@ -1214,11 +1214,11 @@ public:
void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); }
JITSymbol findSymbol(const std::string &Name) {
- return LazyEmitLayer.findSymbol(Name, true);
+ return LazyEmitLayer.findSymbol(Name, false);
}
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) {
- return LazyEmitLayer.findSymbolIn(H, Name, true);
+ return LazyEmitLayer.findSymbolIn(H, Name, false);
}
JITSymbol findUnmangledSymbol(const std::string &Name) {
@@ -1276,7 +1276,7 @@ private:
makeStub(*F, *FunctionBodyPointer);
// Step 4) Add the module containing the stub to the JIT.
- auto H = addModule(C.takeM());
+ auto StubH = addModule(C.takeM());
// Step 5) Set the compile and update actions.
//
@@ -1289,14 +1289,20 @@ private:
// The update action will update FunctionBodyPointer to point at the newly
// compiled function.
std::shared_ptr<FunctionAST> Fn = std::move(FnAST);
- CallbackInfo.setCompileAction([this, Fn]() {
+ CallbackInfo.setCompileAction([this, Fn, BodyPtrName, StubH]() {
auto H = addModule(IRGen(Session, *Fn));
- return findUnmangledSymbolIn(H, Fn->Proto->Name).getAddress();
+ auto BodySym = findUnmangledSymbolIn(H, Fn->Proto->Name);
+ auto BodyPtrSym = findUnmangledSymbolIn(StubH, BodyPtrName);
+ assert(BodySym && "Missing function body.");
+ assert(BodyPtrSym && "Missing function pointer.");
+ auto BodyAddr = BodySym.getAddress();
+ auto BodyPtr = reinterpret_cast<void*>(
+ static_cast<uintptr_t>(BodyPtrSym.getAddress()));
+ memcpy(BodyPtr, &BodyAddr, sizeof(uintptr_t));
+ return BodyAddr;
});
- CallbackInfo.setUpdateAction(
- getLocalFPUpdater(LazyEmitLayer, H, mangle(BodyPtrName)));
- return H;
+ return StubH;
}
SessionContext &Session;
Removed: llvm/trunk/include/llvm/ExecutionEngine/Orc/CloneSubModule.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/CloneSubModule.h?rev=236464&view=auto
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/CloneSubModule.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/CloneSubModule.h (removed)
@@ -1,60 +0,0 @@
-//===-- CloneSubModule.h - Utilities for extracting sub-modules -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Contains utilities for extracting sub-modules. Useful for breaking up modules
-// for lazy jitting.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H
-#define LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H
-
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/Transforms/Utils/ValueMapper.h"
-#include <functional>
-
-namespace llvm {
-
-class Function;
-class GlobalVariable;
-class Module;
-
-namespace orc {
-
-/// @brief Functor type for describing how CloneSubModule should mutate a
-/// GlobalVariable.
-typedef std::function<void(GlobalVariable &, const GlobalVariable &,
- ValueToValueMapTy &)> HandleGlobalVariableFtor;
-
-/// @brief Functor type for describing how CloneSubModule should mutate a
-/// Function.
-typedef std::function<void(Function &, const Function &, ValueToValueMapTy &)>
- HandleFunctionFtor;
-
-/// @brief Copies the initializer from Orig to New.
-///
-/// Type is suitable for implicit conversion to a HandleGlobalVariableFtor.
-void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig,
- ValueToValueMapTy &VMap);
-
-/// @brief Copies the body of Orig to New.
-///
-/// Type is suitable for implicit conversion to a HandleFunctionFtor.
-void copyFunctionBody(Function &New, const Function &Orig,
- ValueToValueMapTy &VMap);
-
-/// @brief Clone a subset of the module Src into Dst.
-void CloneSubModule(Module &Dst, const Module &Src,
- HandleGlobalVariableFtor HandleGlobalVariable,
- HandleFunctionFtor HandleFunction, bool KeepInlineAsm);
-
-} // End namespace orc.
-} // End namespace llvm.
-
-#endif // LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h Mon May 4 17:03:10 2015
@@ -15,110 +15,180 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
+//#include "CloneSubModule.h"
#include "IndirectionUtils.h"
#include "LambdaResolver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/Transforms/Utils/Cloning.h"
#include <list>
+#include <set>
+
+#include "llvm/Support/Debug.h"
namespace llvm {
namespace orc {
/// @brief Compile-on-demand layer.
///
-/// Modules added to this layer have their calls indirected, and are then
-/// broken up into a set of single-function modules, each of which is added
-/// to the layer below in a singleton set. The lower layer can be any layer that
-/// accepts IR module sets.
-///
-/// It is expected that this layer will frequently be used on top of a
-/// LazyEmittingLayer. The combination of the two ensures that each function is
-/// compiled only when it is first called.
+/// 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>
class CompileOnDemandLayer {
private:
- /// @brief Lookup helper that provides compatibility with the classic
- /// static-compilation symbol resolution process.
- ///
- /// The CompileOnDemand (COD) layer splits modules up into multiple
- /// sub-modules, each held in its own llvm::Module instance, in order to
- /// support lazy compilation. When a module that contains private symbols is
- /// broken up symbol linkage changes may be required to enable access to
- /// "private" data that now resides in a different llvm::Module instance. To
- /// retain expected symbol resolution behavior for clients of the COD layer,
- /// the CODScopedLookup class uses a two-tiered lookup system to resolve
- /// symbols. Lookup first scans sibling modules that were split from the same
- /// original module (logical-module scoped lookup), then scans all other
- /// modules that have been added to the lookup scope (logical-dylib scoped
- /// lookup).
- class CODScopedLookup {
+
+ // Utility class for MapValue. Only materializes declarations for global
+ // variables.
+ class GlobalDeclMaterializer : public ValueMaterializer {
+ public:
+ GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {}
+ 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;
+ }
private:
- typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
- typedef std::vector<BaseLayerModuleSetHandleT> SiblingHandlesList;
- typedef std::list<SiblingHandlesList> PseudoDylibModuleSetHandlesList;
+ Module &Dst;
+ };
+
+ 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 {
+ 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:
- /// @brief Handle for a logical module.
- typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle;
- /// @brief Construct a scoped lookup.
- CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
+ typedef unsigned UncompiledPartitionID;
+ typedef typename LogicalModuleList::iterator LMHandle;
- virtual ~CODScopedLookup() {}
+ // Construct a logical dylib.
+ LogicalDylib(CompileOnDemandLayer &CODLayer) : CODLayer(CODLayer) { }
+
+ // Delete this logical dylib, release logical module resources.
+ virtual ~LogicalDylib() {
+ releaseLogicalModuleResources();
+ }
- /// @brief Start a new context for a single logical module.
+ // 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() {
- Handles.push_back(SiblingHandlesList());
- return std::prev(Handles.end());
+ LogicalModules.push_back(LogicalModule());
+ return std::prev(LogicalModules.end());
}
- /// @brief Add a concrete Module's handle to the given logical Module's
- /// lookup scope.
- void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
- LMH->push_back(H);
+ // Set the global-values-and-stubs module handle for this logical module.
+ void setGVsAndStubsHandle(LMHandle LMH, BaseLayerModuleSetHandleT H) {
+ LMH->GVsAndStubsHandle = H;
}
- /// @brief Remove a logical Module from the CODScopedLookup entirely.
- void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); }
+ // Return the global-values-and-stubs module handle for this logical module.
+ BaseLayerModuleSetHandleT getGVsAndStubsHandle(LMHandle LMH) {
+ return LMH->GVsAndStubsHandle;
+ }
- /// @brief Look up a symbol in this context.
- JITSymbol findSymbol(LMHandle LMH, const std::string &Name) {
- if (auto Symbol = findSymbolIn(LMH, Name))
+ // 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 = Handles.begin(), E = Handles.end(); I != E; ++I)
+ for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
+ ++I)
if (I != LMH)
- if (auto Symbol = findSymbolIn(I, Name))
+ if (auto Symbol = getBaseLayer().findSymbolIn(I->GVsAndStubsHandle,
+ Name, false))
return Symbol;
return nullptr;
}
- /// @brief Find an external symbol (via the user supplied SymbolResolver).
+ 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;
+ }
+
+ // Find an external symbol (via the user supplied SymbolResolver).
virtual RuntimeDyld::SymbolInfo
- externalLookup(const std::string &Name) const = 0;
+ findSymbolExternally(const std::string &Name) const = 0;
private:
- JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) {
- for (auto H : *LMH)
- if (auto Symbol = BaseLayer.findSymbolIn(H, Name, false))
- return Symbol;
- return nullptr;
+ 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);
+ }
}
- BaseLayerT &BaseLayer;
- PseudoDylibModuleSetHandlesList Handles;
+ CompileOnDemandLayer &CODLayer;
+ LogicalModuleList LogicalModules;
+ std::vector<std::unique_ptr<UncompiledPartition>> UncompiledPartitions;
};
template <typename ResolverPtrT>
- class CODScopedLookupImpl : public CODScopedLookup {
+ class LogicalDylibImpl : public LogicalDylib {
public:
- CODScopedLookupImpl(BaseLayerT &BaseLayer, ResolverPtrT Resolver)
- : CODScopedLookup(BaseLayer), Resolver(std::move(Resolver)) {}
+ LogicalDylibImpl(CompileOnDemandLayer &CODLayer, ResolverPtrT Resolver)
+ : LogicalDylib(CODLayer), Resolver(std::move(Resolver)) {}
RuntimeDyld::SymbolInfo
- externalLookup(const std::string &Name) const override {
+ findSymbolExternally(const std::string &Name) const override {
return Resolver->findSymbol(Name);
}
@@ -127,44 +197,169 @@ private:
};
template <typename ResolverPtrT>
- static std::shared_ptr<CODScopedLookup>
- createCODScopedLookup(BaseLayerT &BaseLayer,
- ResolverPtrT Resolver) {
- typedef CODScopedLookupImpl<ResolverPtrT> Impl;
- return std::make_shared<Impl>(BaseLayer, std::move(Resolver));
+ static std::unique_ptr<LogicalDylib>
+ createLogicalDylib(CompileOnDemandLayer &CODLayer,
+ ResolverPtrT Resolver) {
+ typedef LogicalDylibImpl<ResolverPtrT> Impl;
+ return llvm::make_unique<Impl>(CODLayer, std::move(Resolver));
}
- typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
- typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT;
+ // 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);
+ }
- struct ModuleSetInfo {
- // Symbol lookup - just one for the whole module set.
- std::shared_ptr<CODScopedLookup> Lookup;
-
- // Logical module handles.
- std::vector<typename CODScopedLookup::LMHandle> LMHandles;
-
- // List of vectors of module set handles:
- // One vector per logical module - each vector holds the handles for the
- // exploded modules for that logical module in the base layer.
- BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles;
-
- ModuleSetInfo(std::shared_ptr<CODScopedLookup> Lookup)
- : Lookup(std::move(Lookup)) {}
-
- void releaseResources(BaseLayerT &BaseLayer) {
- for (auto LMH : LMHandles)
- Lookup->removeLogicalModule(LMH);
- for (auto H : BaseLayerModuleSetHandles)
- BaseLayer.removeModuleSet(H);
+ // 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));
+ }
+
+ LogicalDylib &LD;
+ typename LogicalDylib::LMHandle LMH;
+ std::shared_ptr<Module> SrcM;
+ typename LogicalDylib::UncompiledPartitionID ID;
+ PartitionEntryList PartitionEntries;
};
- typedef std::list<ModuleSetInfo> ModuleSetInfoListT;
+ typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList;
public:
/// @brief Handle to a set of loaded modules.
- typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT;
+ typedef typename LogicalDylibList::iterator ModuleSetHandleT;
/// @brief Construct a compile-on-demand layer instance.
CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
@@ -180,19 +375,23 @@ public:
assert(MemMgr == nullptr &&
"User supplied memory managers not supported with COD yet.");
- // Create a lookup context and ModuleSetInfo for this module set.
- // For the purposes of symbol resolution the set Ms will be treated as if
- // the modules it contained had been linked together as a dylib.
- auto DylibLookup = createCODScopedLookup(BaseLayer, std::move(Resolver));
- ModuleSetHandleT H =
- ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup));
- ModuleSetInfo &MSI = ModuleSetInfos.back();
+ LogicalDylibs.push_back(createLogicalDylib(*this, std::move(Resolver)));
// Process each of the modules in this module set.
- for (auto &M : Ms)
- partitionAndAdd(*M, MSI);
+ 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));
+ }
- return H;
+ return std::prev(LogicalDylibs.end());
}
/// @brief Remove the module represented by the given handle.
@@ -200,8 +399,7 @@ public:
/// This will remove all modules in the layers below that were derived from
/// the module represented by H.
void removeModuleSet(ModuleSetHandleT H) {
- H->releaseResources(BaseLayer);
- ModuleSetInfos.erase(H);
+ LogicalDylibs.erase(H);
}
/// @brief Search for the given named symbol.
@@ -216,149 +414,85 @@ public:
/// below this one.
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
-
- for (auto &BH : H->BaseLayerModuleSetHandles) {
- if (auto Symbol = BaseLayer.findSymbolIn(BH, Name, ExportedSymbolsOnly))
- return Symbol;
- }
- return nullptr;
+ return (*H)->findSymbol(Name, ExportedSymbolsOnly);
}
private:
- void partitionAndAdd(Module &M, ModuleSetInfo &MSI) {
- const char *AddrSuffix = "$orc_addr";
- const char *BodySuffix = "$orc_body";
-
- // We're going to break M up into a bunch of sub-modules, but we want
- // internal linkage symbols to still resolve sensibly. CODScopedLookup
- // provides the "logical module" concept to make this work, so create a
- // new logical module for M.
- auto DylibLookup = MSI.Lookup;
- auto LogicalModule = DylibLookup->createLogicalModule();
- MSI.LMHandles.push_back(LogicalModule);
-
- // Partition M into a "globals and stubs" module, a "common symbols" module,
- // and a list of single-function modules.
- auto PartitionedModule = fullyPartition(M);
- auto StubsModule = std::move(PartitionedModule.GlobalVars);
- auto CommonsModule = std::move(PartitionedModule.Commons);
- auto FunctionModules = std::move(PartitionedModule.Functions);
-
- // Emit the commons stright away.
- auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule);
- BaseLayer.emitAndFinalize(CommonHandle);
-
- // Map of definition names to callback-info data structures. We'll use
- // this to build the compile actions for the stubs below.
- typedef std::map<std::string,
- typename CompileCallbackMgrT::CompileCallbackInfo>
- StubInfoMap;
- StubInfoMap StubInfos;
-
- // Now we need to take each of the extracted Modules and add them to
- // base layer. Each Module will be added individually to make sure they
- // can be compiled separately, and each will get its own lookaside
- // memory manager that will resolve within this logical module first.
- for (auto &SubM : FunctionModules) {
-
- // Keep track of the stubs we create for this module so that we can set
- // their compile actions.
- std::vector<typename StubInfoMap::iterator> NewStubInfos;
-
- // Search for function definitions and insert stubs into the stubs
- // module.
- for (auto &F : *SubM) {
- if (F.isDeclaration())
- continue;
-
- std::string Name = F.getName();
- Function *Proto = StubsModule->getFunction(Name);
- assert(Proto && "Failed to clone function decl into stubs module.");
- auto CallbackInfo =
- CompileCallbackMgr.getCompileCallback(Proto->getContext());
- GlobalVariable *FunctionBodyPointer =
- createImplPointer(*Proto->getType(), *Proto->getParent(),
- Name + AddrSuffix,
- createIRTypedAddress(*Proto->getFunctionType(),
- CallbackInfo.getAddress()));
- makeStub(*Proto, *FunctionBodyPointer);
+ void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcM,
+ std::vector<std::vector<Function*>> Partitions) {
- F.setName(Name + BodySuffix);
- F.setVisibility(GlobalValue::HiddenVisibility);
-
- auto KV = std::make_pair(std::move(Name), std::move(CallbackInfo));
- NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV));
+ // Bump the linkage and rename any anonymous/privote members in SrcM to
+ // ensure that everything will resolve properly after we partition SrcM.
+ makeAllSymbolsExternallyAccessible(*SrcM);
+
+ // Create a logical module handle for SrcM within the logical dylib.
+ auto LMH = LD.createLogicalModule();
+
+ // Create the GVs-and-stubs module.
+ auto GVsAndStubsM = llvm::make_unique<Module>(
+ (SrcM->getName() + ".globals_and_stubs").str(),
+ SrcM->getContext());
+ GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
+ ValueToValueMapTy VMap;
+
+ // 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); });
}
- auto H = addModule(std::move(SubM), MSI, LogicalModule);
-
- // Set the compile actions for this module:
- for (auto &KVPair : NewStubInfos) {
- std::string BodyName = Mangle(KVPair->first + BodySuffix,
- M.getDataLayout());
- auto &CCInfo = KVPair->second;
- CCInfo.setCompileAction(
- [=](){
- return BaseLayer.findSymbolIn(H, BodyName, false).getAddress();
- });
- }
-
- }
-
- // Ok - we've processed all the partitioned modules. Now add the
- // stubs/globals module and set the update actions.
- auto StubsH =
- addModule(std::move(StubsModule), MSI, LogicalModule);
-
- for (auto &KVPair : StubInfos) {
- std::string AddrName = Mangle(KVPair.first + AddrSuffix,
- M.getDataLayout());
- auto &CCInfo = KVPair.second;
- CCInfo.setUpdateAction(
- getLocalFPUpdater(BaseLayer, StubsH, AddrName));
+ UP.setPartitionEntries(std::move(PartitionEntries));
}
- }
- // Add the given Module to the base layer using a memory manager that will
- // perform the appropriate scoped lookup (i.e. will look first with in the
- // module from which it was extracted, then into the set to which that module
- // belonged, and finally externally).
- BaseLayerModuleSetHandleT addModule(
- std::unique_ptr<Module> M,
- ModuleSetInfo &MSI,
- typename CODScopedLookup::LMHandle LogicalModule) {
-
- // Add this module to the JIT with a memory manager that uses the
- // DylibLookup to resolve symbols.
- std::vector<std::unique_ptr<Module>> MSet;
- MSet.push_back(std::move(M));
-
- auto DylibLookup = MSI.Lookup;
- auto Resolver =
- createLambdaResolver(
- [=](const std::string &Name) {
- if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name))
+ // Now clone the global variable declarations.
+ GlobalDeclMaterializer GDMat(*GVsAndStubsM);
+ for (auto &GV : SrcM->globals())
+ if (!GV.isDeclaration())
+ cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
+
+ // Then clone the initializers.
+ for (auto &GV : SrcM->globals())
+ if (!GV.isDeclaration())
+ moveGlobalVariableInitializer(GV, VMap, &GDMat);
+
+ // 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 DylibLookup->externalLookup(Name);
+ return LD.findSymbolExternally(Name);
},
- [=](const std::string &Name) -> RuntimeDyld::SymbolInfo {
- if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name))
- return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
- Symbol.getFlags());
- return nullptr;
+ [&LD](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
});
- BaseLayerModuleSetHandleT H =
- BaseLayer.addModuleSet(std::move(MSet),
- make_unique<SectionMemoryManager>(),
- std::move(Resolver));
- // Add this module to the logical module lookup.
- DylibLookup->addToLogicalModule(LogicalModule, H);
- MSI.BaseLayerModuleSetHandles.push_back(H);
-
- return H;
+ std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
+ GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
+ auto GVsAndStubsH =
+ BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
+ llvm::make_unique<SectionMemoryManager>(),
+ std::move(GVsAndStubsResolver));
+ LD.setGVsAndStubsHandle(LMH, GVsAndStubsH);
}
static std::string Mangle(StringRef Name, const DataLayout &DL) {
@@ -373,9 +507,33 @@ private:
BaseLayerT &BaseLayer;
CompileCallbackMgrT &CompileCallbackMgr;
- ModuleSetInfoListT ModuleSetInfos;
+ LogicalDylibList LogicalDylibs;
};
+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.
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h Mon May 4 17:03:10 2015
@@ -21,6 +21,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
#include <sstream>
namespace llvm {
@@ -32,28 +33,22 @@ class JITCompileCallbackManagerBase {
public:
typedef std::function<TargetAddress()> CompileFtor;
- typedef std::function<void(TargetAddress)> UpdateFtor;
/// @brief Handle to a newly created compile callback. Can be used to get an
/// IR constant representing the address of the trampoline, and to set
- /// the compile and update actions for the callback.
+ /// the compile action for the callback.
class CompileCallbackInfo {
public:
- CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile,
- UpdateFtor &Update)
- : Addr(Addr), Compile(Compile), Update(Update) {}
+ CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile)
+ : Addr(Addr), Compile(Compile) {}
TargetAddress getAddress() const { return Addr; }
void setCompileAction(CompileFtor Compile) {
this->Compile = std::move(Compile);
}
- void setUpdateAction(UpdateFtor Update) {
- this->Update = std::move(Update);
- }
private:
TargetAddress Addr;
CompileFtor &Compile;
- UpdateFtor &Update;
};
/// @brief Construct a JITCompileCallbackManagerBase.
@@ -71,8 +66,8 @@ public:
/// @brief Execute the callback for the given trampoline id. Called by the JIT
/// to compile functions on demand.
- TargetAddress executeCompileCallback(TargetAddress TrampolineID) {
- TrampolineMapT::iterator I = ActiveTrampolines.find(TrampolineID);
+ TargetAddress executeCompileCallback(TargetAddress TrampolineAddr) {
+ auto I = ActiveTrampolines.find(TrampolineAddr);
// FIXME: Also raise an error in the Orc error-handler when we finally have
// one.
if (I == ActiveTrampolines.end())
@@ -84,31 +79,43 @@ public:
// Moving the trampoline ID back to the available list first means there's at
// least one available trampoline if the compile action triggers a request for
// a new one.
- AvailableTrampolines.push_back(I->first);
- auto CallbackHandler = std::move(I->second);
+ auto Compile = std::move(I->second);
ActiveTrampolines.erase(I);
+ AvailableTrampolines.push_back(TrampolineAddr);
- if (auto Addr = CallbackHandler.Compile()) {
- CallbackHandler.Update(Addr);
+ if (auto Addr = Compile())
return Addr;
- }
+
return ErrorHandlerAddress;
}
- /// @brief Get/create a compile callback with the given signature.
+ /// @brief Reserve a compile callback.
virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0;
-protected:
+ /// @brief Get a CompileCallbackInfo for an existing callback.
+ CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) {
+ auto I = ActiveTrampolines.find(TrampolineAddr);
+ assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
+ return CompileCallbackInfo(I->first, I->second);
+ }
- struct CallbackHandler {
- CompileFtor Compile;
- UpdateFtor Update;
- };
+ /// @brief Release a compile callback.
+ ///
+ /// Note: Callbacks are auto-released after they execute. This method should
+ /// only be called to manually release a callback that is not going to
+ /// execute.
+ void releaseCompileCallback(TargetAddress TrampolineAddr) {
+ auto I = ActiveTrampolines.find(TrampolineAddr);
+ assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
+ ActiveTrampolines.erase(I);
+ AvailableTrampolines.push_back(TrampolineAddr);
+ }
+protected:
TargetAddress ErrorHandlerAddress;
unsigned NumTrampolinesPerBlock;
- typedef std::map<TargetAddress, CallbackHandler> TrampolineMapT;
+ typedef std::map<TargetAddress, CompileFtor> TrampolineMapT;
TrampolineMapT ActiveTrampolines;
std::vector<TargetAddress> AvailableTrampolines;
};
@@ -140,11 +147,8 @@ public:
/// @brief Get/create a compile callback with the given signature.
CompileCallbackInfo getCompileCallback(LLVMContext &Context) final {
TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context);
- auto &CallbackHandler =
- this->ActiveTrampolines[TrampolineAddr];
-
- return CompileCallbackInfo(TrampolineAddr, CallbackHandler.Compile,
- CallbackHandler.Update);
+ auto &Compile = this->ActiveTrampolines[TrampolineAddr];
+ return CompileCallbackInfo(TrampolineAddr, Compile);
}
private:
@@ -218,22 +222,6 @@ private:
TargetAddress ResolverBlockAddr;
};
-/// @brief Get an update functor that updates the value of a named function
-/// pointer.
-template <typename JITLayerT>
-JITCompileCallbackManagerBase::UpdateFtor
-getLocalFPUpdater(JITLayerT &JIT, typename JITLayerT::ModuleSetHandleT H,
- std::string Name) {
- // FIXME: Move-capture Name once we can use C++14.
- return [=,&JIT](TargetAddress Addr) {
- auto FPSym = JIT.findSymbolIn(H, Name, true);
- assert(FPSym && "Cannot find function pointer to update.");
- void *FPAddr = reinterpret_cast<void*>(
- static_cast<uintptr_t>(FPSym.getAddress()));
- memcpy(FPAddr, &Addr, sizeof(uintptr_t));
- };
- }
-
/// @brief Build a function pointer of FunctionType with the given constant
/// address.
///
@@ -250,27 +238,56 @@ GlobalVariable* createImplPointer(Pointe
/// indirect call using the given function pointer.
void makeStub(Function &F, GlobalVariable &ImplPointer);
-typedef std::map<Module*, DenseSet<const GlobalValue*>> ModulePartitionMap;
+/// @brief Raise linkage types and rename as necessary to ensure that all
+/// symbols are accessible for other modules.
+///
+/// This should be called before partitioning a module to ensure that the
+/// partitions retain access to each other's symbols.
+void makeAllSymbolsExternallyAccessible(Module &M);
-/// @brief Extract subsections of a Module into the given Module according to
-/// the given ModulePartitionMap.
-void partition(Module &M, const ModulePartitionMap &PMap);
+/// @brief Clone a function declaration into a new module.
+///
+/// This function can be used as the first step towards creating a callback
+/// stub (see makeStub), or moving a function body (see moveFunctionBody).
+///
+/// If the VMap argument is non-null, a mapping will be added between F and
+/// the new declaration, and between each of F's arguments and the new
+/// declaration's arguments. This map can then be passed in to moveFunction to
+/// move the function body if required. Note: When moving functions between
+/// modules with these utilities, all decls should be cloned (and added to a
+/// single VMap) before any bodies are moved. This will ensure that references
+/// between functions all refer to the versions in the new module.
+Function* cloneFunctionDecl(Module &Dst, const Function &F,
+ ValueToValueMapTy *VMap = nullptr);
-/// @brief Struct for trivial "complete" partitioning of a module.
-class FullyPartitionedModule {
-public:
- std::unique_ptr<Module> GlobalVars;
- std::unique_ptr<Module> Commons;
- std::vector<std::unique_ptr<Module>> Functions;
-
- FullyPartitionedModule() = default;
- FullyPartitionedModule(FullyPartitionedModule &&S)
- : GlobalVars(std::move(S.GlobalVars)), Commons(std::move(S.Commons)),
- Functions(std::move(S.Functions)) {}
-};
+/// @brief Move the body of function 'F' to a cloned function declaration in a
+/// different module (See related cloneFunctionDecl).
+///
+/// If the target function declaration is not supplied via the NewF parameter
+/// then it will be looked up via the VMap.
+///
+/// This will delete the body of function 'F' from its original parent module,
+/// but leave its declaration.
+void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
+ ValueMaterializer *Materializer = nullptr,
+ Function *NewF = nullptr);
+
+/// @brief Clone a global variable declaration into a new module.
+GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
+ ValueToValueMapTy *VMap = nullptr);
-/// @brief Extract every function in M into a separate module.
-FullyPartitionedModule fullyPartition(Module &M);
+/// @brief Move global variable GV from its parent module to cloned global
+/// declaration in a different module.
+///
+/// If the target global declaration is not supplied via the NewGV parameter
+/// then it will be looked up via the VMap.
+///
+/// This will delete the initializer of GV from its original parent module,
+/// but leave its declaration.
+void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
+ ValueToValueMapTy &VMap,
+ ValueMaterializer *Materializer = nullptr,
+ GlobalVariable *NewGV = nullptr);
} // End namespace orc.
} // End namespace llvm.
Modified: llvm/trunk/lib/ExecutionEngine/Orc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/CMakeLists.txt?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/CMakeLists.txt (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/CMakeLists.txt Mon May 4 17:03:10 2015
@@ -1,5 +1,4 @@
add_llvm_library(LLVMOrcJIT
- CloneSubModule.cpp
ExecutionUtils.cpp
IndirectionUtils.cpp
OrcMCJITReplacement.cpp
Removed: llvm/trunk/lib/ExecutionEngine/Orc/CloneSubModule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/CloneSubModule.cpp?rev=236464&view=auto
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/CloneSubModule.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/CloneSubModule.cpp (removed)
@@ -1,106 +0,0 @@
-#include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/GlobalVariable.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Transforms/Utils/Cloning.h"
-
-namespace llvm {
-namespace orc {
-
-void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig,
- ValueToValueMapTy &VMap) {
- if (Orig.hasInitializer())
- New.setInitializer(MapValue(Orig.getInitializer(), VMap));
-}
-
-void copyFunctionBody(Function &New, const Function &Orig,
- ValueToValueMapTy &VMap) {
- if (!Orig.isDeclaration()) {
- Function::arg_iterator DestI = New.arg_begin();
- for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end();
- ++J) {
- DestI->setName(J->getName());
- VMap[J] = DestI++;
- }
-
- SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
- CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns);
- }
-}
-
-void CloneSubModule(llvm::Module &Dst, const Module &Src,
- HandleGlobalVariableFtor HandleGlobalVariable,
- HandleFunctionFtor HandleFunction, bool CloneInlineAsm) {
-
- ValueToValueMapTy VMap;
-
- if (CloneInlineAsm)
- Dst.appendModuleInlineAsm(Src.getModuleInlineAsm());
-
- // Copy global variables (but not initializers, yet).
- for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end();
- I != E; ++I) {
- GlobalVariable *GV = new GlobalVariable(
- Dst, I->getType()->getElementType(), I->isConstant(), I->getLinkage(),
- (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr,
- I->getThreadLocalMode(), I->getType()->getAddressSpace());
- GV->copyAttributesFrom(I);
- VMap[I] = GV;
- }
-
- // Loop over the functions in the module, making external functions as before
- for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) {
- Function *NF =
- Function::Create(cast<FunctionType>(I->getType()->getElementType()),
- I->getLinkage(), I->getName(), &Dst);
- NF->copyAttributesFrom(I);
- VMap[I] = NF;
- }
-
- // Loop over the aliases in the module
- for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end();
- I != E; ++I) {
- auto *PTy = cast<PointerType>(I->getType());
- auto *GA = GlobalAlias::create(PTy, I->getLinkage(), I->getName(), &Dst);
- GA->copyAttributesFrom(I);
- VMap[I] = GA;
- }
-
- // Now that all of the things that global variable initializer can refer to
- // have been created, loop through and copy the global variable referrers
- // over... We also set the attributes on the global now.
- for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end();
- I != E; ++I) {
- GlobalVariable &GV = *cast<GlobalVariable>(VMap[I]);
- HandleGlobalVariable(GV, *I, VMap);
- }
-
- // Similarly, copy over function bodies now...
- //
- for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) {
- Function &F = *cast<Function>(VMap[I]);
- HandleFunction(F, *I, VMap);
- }
-
- // And aliases
- for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end();
- I != E; ++I) {
- GlobalAlias *GA = cast<GlobalAlias>(VMap[I]);
- if (const Constant *C = I->getAliasee())
- GA->setAliasee(MapValue(C, VMap));
- }
-
- // And named metadata....
- for (Module::const_named_metadata_iterator I = Src.named_metadata_begin(),
- E = Src.named_metadata_end();
- I != E; ++I) {
- const NamedMDNode &NMD = *I;
- NamedMDNode *NewNMD = Dst.getOrInsertNamedMetadata(NMD.getName());
- for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
- NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap));
- }
-
-}
-
-} // End namespace orc.
-} // End namespace llvm.
Modified: llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp Mon May 4 17:03:10 2015
@@ -9,10 +9,10 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/Transforms/Utils/Cloning.h"
#include <set>
#include <sstream>
@@ -32,9 +32,11 @@ GlobalVariable* createImplPointer(Pointe
const Twine &Name, Constant *Initializer) {
if (!Initializer)
Initializer = Constant::getNullValue(&PT);
- return new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
- Initializer, Name, nullptr,
- GlobalValue::NotThreadLocal, 0, true);
+ auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
+ Initializer, Name, nullptr,
+ GlobalValue::NotThreadLocal, 0, true);
+ IP->setVisibility(GlobalValue::HiddenVisibility);
+ return IP;
}
void makeStub(Function &F, GlobalVariable &ImplPointer) {
@@ -50,7 +52,10 @@ void makeStub(Function &F, GlobalVariabl
CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs);
Call->setTailCall();
Call->setAttributes(F.getAttributes());
- Builder.CreateRet(Call);
+ if (F.getReturnType()->isVoidTy())
+ Builder.CreateRetVoid();
+ else
+ Builder.CreateRet(Call);
}
// Utility class for renaming global values and functions during partitioning.
@@ -84,83 +89,94 @@ private:
DenseMap<const Value*, std::string> Names;
};
-void partition(Module &M, const ModulePartitionMap &PMap) {
+static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) {
+ if (V.hasLocalLinkage()) {
+ if (R.needsRenaming(V))
+ V.setName(R.getRename(V));
+ V.setLinkage(GlobalValue::ExternalLinkage);
+ V.setVisibility(GlobalValue::HiddenVisibility);
+ }
+ V.setUnnamedAddr(false);
+ assert(!R.needsRenaming(V) && "Invalid global name.");
+}
+void makeAllSymbolsExternallyAccessible(Module &M) {
GlobalRenamer Renamer;
- for (auto &KVPair : PMap) {
+ for (auto &F : M)
+ raiseVisibilityOnValue(F, Renamer);
- auto ExtractGlobalVars =
- [&](GlobalVariable &New, const GlobalVariable &Orig,
- ValueToValueMapTy &VMap) {
- if (KVPair.second.count(&Orig)) {
- copyGVInitializer(New, Orig, VMap);
- }
- if (New.hasLocalLinkage()) {
- if (Renamer.needsRenaming(New))
- New.setName(Renamer.getRename(Orig));
- New.setLinkage(GlobalValue::ExternalLinkage);
- New.setVisibility(GlobalValue::HiddenVisibility);
- }
- assert(!Renamer.needsRenaming(New) && "Invalid global name.");
- };
-
- auto ExtractFunctions =
- [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
- if (KVPair.second.count(&Orig))
- copyFunctionBody(New, Orig, VMap);
- if (New.hasLocalLinkage()) {
- if (Renamer.needsRenaming(New))
- New.setName(Renamer.getRename(Orig));
- New.setLinkage(GlobalValue::ExternalLinkage);
- New.setVisibility(GlobalValue::HiddenVisibility);
- }
- assert(!Renamer.needsRenaming(New) && "Invalid function name.");
- };
-
- CloneSubModule(*KVPair.first, M, ExtractGlobalVars, ExtractFunctions,
- false);
- }
+ for (auto &GV : M.globals())
+ raiseVisibilityOnValue(GV, Renamer);
}
-FullyPartitionedModule fullyPartition(Module &M) {
- FullyPartitionedModule MP;
-
- ModulePartitionMap PMap;
-
- for (auto &F : M) {
+Function* cloneFunctionDecl(Module &Dst, const Function &F,
+ ValueToValueMapTy *VMap) {
+ assert(F.getParent() != &Dst && "Can't copy decl over existing function.");
+ Function *NewF =
+ Function::Create(cast<FunctionType>(F.getType()->getElementType()),
+ F.getLinkage(), F.getName(), &Dst);
+ NewF->copyAttributesFrom(&F);
+
+ if (VMap) {
+ (*VMap)[&F] = NewF;
+ auto NewArgI = NewF->arg_begin();
+ for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
+ ++ArgI, ++NewArgI)
+ (*VMap)[ArgI] = NewArgI;
+ }
- if (F.isDeclaration())
- continue;
+ return NewF;
+}
- std::string NewModuleName = (M.getName() + "." + F.getName()).str();
- MP.Functions.push_back(
- llvm::make_unique<Module>(NewModuleName, M.getContext()));
- MP.Functions.back()->setDataLayout(M.getDataLayout());
- PMap[MP.Functions.back().get()].insert(&F);
- }
+void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
+ ValueMaterializer *Materializer,
+ Function *NewF) {
+ assert(!OrigF.isDeclaration() && "Nothing to move");
+ if (!NewF)
+ NewF = cast<Function>(VMap[&OrigF]);
+ else
+ assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
+ assert(NewF && "Function mapping missing from VMap.");
+ assert(NewF->getParent() != OrigF.getParent() &&
+ "moveFunctionBody should only be used to move bodies between "
+ "modules.");
+
+ SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
+ CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns,
+ "", nullptr, nullptr, Materializer);
+ OrigF.deleteBody();
+}
- MP.GlobalVars =
- llvm::make_unique<Module>((M.getName() + ".globals_and_stubs").str(),
- M.getContext());
- MP.GlobalVars->setDataLayout(M.getDataLayout());
-
- MP.Commons =
- llvm::make_unique<Module>((M.getName() + ".commons").str(), M.getContext());
- MP.Commons->setDataLayout(M.getDataLayout());
-
- // Make sure there's at least an empty set for the stubs map or we'll fail
- // to clone anything for it (including the decls).
- PMap[MP.GlobalVars.get()] = ModulePartitionMap::mapped_type();
- for (auto &GV : M.globals())
- if (GV.getLinkage() == GlobalValue::CommonLinkage)
- PMap[MP.Commons.get()].insert(&GV);
- else
- PMap[MP.GlobalVars.get()].insert(&GV);
+GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
+ ValueToValueMapTy *VMap) {
+ assert(GV.getParent() != &Dst && "Can't copy decl over existing global var.");
+ GlobalVariable *NewGV = new GlobalVariable(
+ Dst, GV.getType()->getElementType(), GV.isConstant(),
+ GV.getLinkage(), nullptr, GV.getName(), nullptr,
+ GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
+ NewGV->copyAttributesFrom(&GV);
+ if (VMap)
+ (*VMap)[&GV] = NewGV;
+ return NewGV;
+}
- partition(M, PMap);
+void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
+ ValueToValueMapTy &VMap,
+ ValueMaterializer *Materializer,
+ GlobalVariable *NewGV) {
+ assert(OrigGV.hasInitializer() && "Nothing to move");
+ if (!NewGV)
+ NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
+ else
+ assert(VMap[&OrigGV] == NewGV &&
+ "Incorrect global variable mapping in VMap.");
+ assert(NewGV->getParent() != OrigGV.getParent() &&
+ "moveGlobalVariable should only be used to move initializers between "
+ "modules");
- return MP;
+ NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
+ nullptr, Materializer));
}
} // End namespace orc.
Modified: llvm/trunk/test/ExecutionEngine/OrcLazy/hello.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/OrcLazy/hello.ll?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/OrcLazy/hello.ll (original)
+++ llvm/trunk/test/ExecutionEngine/OrcLazy/hello.ll Mon May 4 17:03:10 2015
@@ -1,7 +1,7 @@
; RUN: lli -jit-kind=orc-lazy -orc-lazy-debug=funcs-to-stdout %s | FileCheck %s
;
; CHECK: Hello
-; CHECK: [ {{.*}}main$orc_body ]
+; CHECK: [ {{.*}}main ]
; CHECK: Goodbye
%class.Foo = type { i8 }
Modified: llvm/trunk/tools/lli/OrcLazyJIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/OrcLazyJIT.h?rev=236465&r1=236464&r2=236465&view=diff
==============================================================================
--- llvm/trunk/tools/lli/OrcLazyJIT.h (original)
+++ llvm/trunk/tools/lli/OrcLazyJIT.h Mon May 4 17:03:10 2015
@@ -21,7 +21,6 @@
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
-#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/IR/LLVMContext.h"
@@ -37,9 +36,7 @@ public:
typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
TransformFtor;
typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT;
- typedef orc::LazyEmittingLayer<IRDumpLayerT> LazyEmitLayerT;
- typedef orc::CompileOnDemandLayer<LazyEmitLayerT,
- CompileCallbackMgr> CODLayerT;
+ typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT;
typedef CODLayerT::ModuleSetHandleT ModuleHandleT;
typedef std::function<
@@ -57,9 +54,8 @@ public:
ObjectLayer(),
CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
IRDumpLayer(CompileLayer, createDebugDumper()),
- LazyEmitLayer(IRDumpLayer),
CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)),
- CODLayer(LazyEmitLayer, *CCMgr),
+ CODLayer(IRDumpLayer, *CCMgr),
CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
~OrcLazyJIT() {
@@ -154,7 +150,6 @@ private:
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
IRDumpLayerT IRDumpLayer;
- LazyEmitLayerT LazyEmitLayer;
std::unique_ptr<CompileCallbackMgr> CCMgr;
CODLayerT CODLayer;
More information about the llvm-commits
mailing list