IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
- OptimizeLayer(CompileLayer, [this](std::unique_ptr<Module> M) {
+ OptimizeLayer(CompileLayer, [this](std::shared_ptr<Module> M) {
return optimizeModule(std::move(M));
}) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
private:
- std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
+ std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
// Create a function pass manager.
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
- [this](std::unique_ptr<Module> M) {
+ [this](std::shared_ptr<Module> M) {
return optimizeModule(std::move(M));
}),
CompileCallbackManager(
}
private:
- std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
+ std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
// Create a function pass manager.
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
- [this](std::unique_ptr<Module> M) {
+ [this](std::shared_ptr<Module> M) {
return optimizeModule(std::move(M));
}),
CompileCallbackMgr(
return MangledNameStream.str();
}
- std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
+ std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
// Create a function pass manager.
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
- [this](std::unique_ptr<Module> M) {
+ [this](std::shared_ptr<Module> M) {
return optimizeModule(std::move(M));
}),
Remote(Remote) {
return MangledNameStream.str();
}
- std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
+ std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
// Create a function pass manager.
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
extern "C" {
#endif
+typedef struct LLVMOpaqueSharedModule *LLVMSharedModuleRef;
typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
typedef uint64_t LLVMOrcModuleHandle;
typedef uint64_t LLVMOrcTargetAddress;
typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode;
/**
+ * Turn an LLVMModuleRef into an LLVMSharedModuleRef.
+ *
+ * The JIT uses shared ownership for LLVM modules, since it is generally
+ * difficult to know when the JIT will be finished with a module (and the JIT
+ * has no way of knowing when a user may be finished with one).
+ *
+ * Calling this method with an LLVMModuleRef creates a shared-pointer to the
+ * module, and returns a reference to this shared pointer.
+ *
+ * The shared module should be disposed when finished with by calling
+ * LLVMOrcDisposeSharedModule (not LLVMDisposeModule). The Module will be
+ * deleted when the last shared pointer owner relinquishes it.
+ */
+
+LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod);
+
+/**
+ * Dispose of a shared module.
+ *
+ * The module should not be accessed after this call. The module will be
+ * deleted once all clients (including the JIT itself) have released their
+ * shared pointers.
+ */
+
+void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod);
+
+/**
* Create an ORC JIT stack.
*
* The client owns the resulting stack, and must call OrcDisposeInstance(...)
LLVMOrcErrorCode
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
- LLVMModuleRef Mod,
+ LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
LLVMOrcErrorCode
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
- LLVMModuleRef Mod,
+ LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
struct LogicalDylib {
struct SourceModuleEntry {
- std::unique_ptr<Module> SourceMod;
+ std::shared_ptr<Module> SourceMod;
std::set<Function*> StubsToClone;
};
StubsMgr(std::move(StubsMgr)) {}
SourceModuleHandle
- addSourceModule(std::unique_ptr<Module> M) {
+ addSourceModule(std::shared_ptr<Module> M) {
SourceModuleHandle H = SourceModules.size();
SourceModules.push_back(SourceModuleEntry());
SourceModules.back().SourceMod = std::move(M);
}
/// @brief Add a module to the compile-on-demand layer.
- Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
+ Error addModule(VModuleKey K, std::shared_ptr<Module> M) {
assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
auto I = LogicalDylibs.insert(
}
/// @brief Add extra modules to an existing logical module.
- Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
+ Error addExtraModule(VModuleKey K, std::shared_ptr<Module> M) {
return addLogicalModule(LogicalDylibs[K], std::move(M));
}
private:
- Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
+ Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) {
// Rename all static functions / globals to $static.X :
// This will unique the names across all modules in the logical dylib,
class IRCompileLayer {
public:
- /// @brief Callback type for notifications when modules are compiled.
- using NotifyCompiledCallback = std::function<void(VModuleKey K,
- std::unique_ptr<Module>)>;
-
/// @brief Construct an IRCompileLayer with the given BaseLayer, which must
/// implement the ObjectLayer concept.
- IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile,
- NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback())
- : BaseLayer(BaseLayer), Compile(std::move(Compile)),
- NotifyCompiled(std::move(NotifyCompiled)) {}
+ IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
+ : BaseLayer(BaseLayer), Compile(std::move(Compile)) {}
/// @brief Get a reference to the compiler functor.
CompileFtor& getCompiler() { return Compile; }
- /// @brief (Re)set the NotifyCompiled callback.
- void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) {
- this->NotifyCompiled = std::move(NotifyCompiled);
- }
-
/// @brief Compile the module, and add the resulting object to the base layer
/// 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();
+ Error addModule(VModuleKey K, std::shared_ptr<Module> M) {
+ return BaseLayer.addObject(std::move(K), Compile(*M));
}
/// @brief Remove the module associated with the VModuleKey K.
private:
BaseLayerT &BaseLayer;
CompileFtor Compile;
- NotifyCompiledCallback NotifyCompiled;
};
} // end namespace orc
/// 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) {
+ Error addModule(VModuleKey K, std::shared_ptr<Module> M) {
return BaseLayer.addModule(std::move(K), Transform(std::move(M)));
}
/// 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)
+ EmissionDeferredModule(VModuleKey K, std::shared_ptr<Module> M)
: K(std::move(K)), M(std::move(M)) {}
JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
VModuleKey K;
- std::unique_ptr<Module> M;
+ std::shared_ptr<Module> M;
mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
};
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
/// @brief Add the given module to the lazy emitting layer.
- Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
+ Error addModule(VModuleKey K, std::shared_ptr<Module> M) {
assert(!ModuleMap.count(K) && "VModuleKey K already in use");
ModuleMap[K] =
llvm::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
using namespace llvm;
+LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod) {
+ return wrap(new std::shared_ptr<Module>(unwrap(Mod)));
+}
+
+void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod) {
+ delete unwrap(SharedMod);
+}
+
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) {
TargetMachine *TM2(unwrap(TM));
LLVMOrcErrorCode
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
- LLVMModuleRef Mod,
+ LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
- std::unique_ptr<Module> M(unwrap(Mod));
- return J.addIRModuleEager(*RetHandle, std::move(M), SymbolResolver,
- SymbolResolverCtx);
+ std::shared_ptr<Module> *M(unwrap(Mod));
+ return J.addIRModuleEager(*RetHandle, *M, SymbolResolver, SymbolResolverCtx);
}
LLVMOrcErrorCode
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
- LLVMModuleRef Mod,
+ LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
- std::unique_ptr<Module> M(unwrap(Mod));
- return J.addIRModuleLazy(*RetHandle, std::move(M), SymbolResolver,
- SymbolResolverCtx);
+ std::shared_ptr<Module> *M(unwrap(Mod));
+ return J.addIRModuleLazy(*RetHandle, *M, SymbolResolver, SymbolResolverCtx);
}
LLVMOrcErrorCode
class OrcCBindingsStack;
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<Module>,
+ LLVMSharedModuleRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
}
template <typename LayerT>
LLVMOrcErrorCode
- addIRModule(orc::VModuleKey &RetKey, LayerT &Layer, std::unique_ptr<Module> M,
+ addIRModule(orc::VModuleKey &RetKey, LayerT &Layer, std::shared_ptr<Module> M,
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
}
LLVMOrcErrorCode addIRModuleEager(orc::VModuleKey &RetKey,
- std::unique_ptr<Module> M,
+ std::shared_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(RetKey, CompileLayer, std::move(M),
}
LLVMOrcErrorCode addIRModuleLazy(orc::VModuleKey &RetKey,
- std::unique_ptr<Module> M,
+ std::shared_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(RetKey, CODLayer, std::move(M),
}
void OrcMCJITReplacement::runStaticConstructorsDestructors(bool isDtors) {
- for (auto &M : Modules)
+ for (auto &M : LocalModules)
ExecutionEngine::runStaticConstructorsDestructors(*M, isDtors);
}
namespace orc {
class OrcMCJITReplacement : public ExecutionEngine {
-
// OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
// Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
// expecting - see finalizeMemory.
return ObjectLayerT::Resources{this->MemMgr, this->Resolver};
},
NotifyObjectLoaded, NotifyFinalized),
- CompileLayer(ObjectLayer, SimpleCompiler(*this->TM),
- [this](VModuleKey K, std::unique_ptr<Module> M) {
- Modules.push_back(std::move(M));
- }),
+ CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
LazyEmitLayer(CompileLayer) {}
static void Register() {
} else {
assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
}
- cantFail(LazyEmitLayer.addModule(ES.allocateVModule(), std::move(M)));
+ auto *MPtr = M.release();
+ ShouldDelete[MPtr] = true;
+ auto Deleter = [this](Module *Mod) {
+ auto I = ShouldDelete.find(Mod);
+ if (I != ShouldDelete.end() && I->second)
+ delete Mod;
+ };
+ LocalModules.push_back(std::shared_ptr<Module>(MPtr, std::move(Deleter)));
+ cantFail(
+ LazyEmitLayer.addModule(ES.allocateVModule(), LocalModules.back()));
}
void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
}
bool removeModule(Module *M) override {
- auto I = Modules.begin();
- for (auto E = Modules.end(); I != E; ++I)
- if (I->get() == M)
- break;
- if (I == Modules.end())
- return false;
- Modules.erase(I);
- return true;
+ for (auto I = LocalModules.begin(), E = LocalModules.end(); I != E; ++I) {
+ if (I->get() == M) {
+ ShouldDelete[M] = false;
+ LocalModules.erase(I);
+ return true;
+ }
+ }
+ return false;
}
uint64_t getSymbolAddress(StringRef Name) {
// delete blocks in LocalModules refer to the ShouldDelete map, so
// LocalModules needs to be destructed before ShouldDelete.
std::map<Module*, bool> ShouldDelete;
+ std::vector<std::shared_ptr<Module>> LocalModules;
NotifyObjectLoadedT NotifyObjectLoaded;
NotifyFinalizedT NotifyFinalized;
OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
switch (OrcDumpKind) {
case DumpKind::NoDump:
- return [](std::unique_ptr<Module> M) { return M; };
+ return [](std::shared_ptr<Module> M) { return M; };
case DumpKind::DumpFuncsToStdOut:
- return [](std::unique_ptr<Module> M) {
+ return [](std::shared_ptr<Module> M) {
printf("[ ");
for (const auto &F : *M) {
};
case DumpKind::DumpModsToStdOut:
- return [](std::unique_ptr<Module> M) {
+ return [](std::shared_ptr<Module> M) {
outs() << "----- Module Start -----\n" << *M
<< "----- Module End -----\n";
};
case DumpKind::DumpModsToDisk:
- return [](std::unique_ptr<Module> M) {
+ return [](std::shared_ptr<Module> M) {
std::error_code EC;
raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
sys::fs::F_Text);
// Add the module, look up main and run it.
for (auto &M : Ms)
- cantFail(J.addModule(std::move(M)));
+ cantFail(J.addModule(std::shared_ptr<Module>(std::move(M))));
if (auto MainSym = J.findSymbol("main")) {
typedef int (*MainFnPtr)(int, const char*[]);
using ObjLayerT = orc::RTDyldObjectLinkingLayer;
using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
using TransformFtor =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
using IRDumpLayerT = orc::IRTransformLayer<CompileLayerT, TransformFtor>;
using CODLayerT = orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr>;
using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
}
}
- Error addModule(std::unique_ptr<Module> M) {
+ Error addModule(std::shared_ptr<Module> M) {
if (M->getDataLayout().isDefault())
M->setDataLayout(DL);
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/Module.h"
#include "llvm/Object/ObjectFile.h"
#include "gtest/gtest.h"
// Make sure that the calls from IRCompileLayer to ObjectTransformLayer
// compile.
cantFail(CompileLayer.addModule(ES.allocateVModule(),
- std::unique_ptr<llvm::Module>()));
+ std::shared_ptr<llvm::Module>()));
// Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer
// compile.
CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
auto *ET = CCtx->APIExecTest;
CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
- LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, wrap(CCtx->M.release()),
- myResolver, nullptr);
+ LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(CCtx->M.release()));
+ LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, SM, myResolver, nullptr);
+ LLVMOrcDisposeSharedModuleRef(SM);
CCtx->Compiled = true;
LLVMOrcTargetAddress MainAddr;
LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main");
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+ LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
LLVMOrcModuleHandle H;
- LLVMOrcAddEagerlyCompiledIR(JIT, &H, wrap(M.release()), myResolver, nullptr);
+ LLVMOrcAddEagerlyCompiledIR(JIT, &H, SM, myResolver, nullptr);
+ LLVMOrcDisposeSharedModuleRef(SM);
LLVMOrcTargetAddress MainAddr;
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
MainFnTy MainFn = (MainFnTy)MainAddr;
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+ LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
LLVMOrcModuleHandle H;
- LLVMOrcAddLazilyCompiledIR(JIT, &H, wrap(M.release()), myResolver, nullptr);
+ LLVMOrcAddLazilyCompiledIR(JIT, &H, SM, myResolver, nullptr);
+ LLVMOrcDisposeSharedModuleRef(SM);
LLVMOrcTargetAddress MainAddr;
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
MainFnTy MainFn = (MainFnTy)MainAddr;