1 //===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // JIT layer for breaking up modules and inserting callbacks to allow
11 // individual functions to be compiled on demand.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
18 #include "IndirectionUtils.h"
19 #include "LambdaResolver.h"
20 #include "LogicalDylib.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
23 #include "llvm/Transforms/Utils/Cloning.h"
27 #include "llvm/Support/Debug.h"
32 /// @brief Compile-on-demand layer.
34 /// When a module is added to this layer a stub is created for each of its
35 /// function definitions. The stubs and other global values are immediately
36 /// added to the layer below. When a stub is called it triggers the extraction
37 /// of the function body from the original module. The extracted body is then
38 /// compiled and executed.
39 template <typename BaseLayerT, typename CompileCallbackMgrT,
40 typename PartitioningFtor =
41 std::function<std::set<Function*>(Function&)>>
42 class CompileOnDemandLayer {
45 // Utility class for MapValue. Only materializes declarations for global
47 class GlobalDeclMaterializer : public ValueMaterializer {
49 GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {}
50 Value* materializeValueFor(Value *V) final {
51 if (auto *GV = dyn_cast<GlobalVariable>(V))
52 return cloneGlobalVariableDecl(Dst, *GV);
53 else if (auto *F = dyn_cast<Function>(V))
54 return cloneFunctionDecl(Dst, *F);
62 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
64 struct LogicalModuleResources {
65 std::shared_ptr<Module> SourceModule;
68 struct LogicalDylibResources {
69 typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
71 SymbolResolverFtor ExternalSymbolResolver;
72 PartitioningFtor Partitioner;
75 typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
76 LogicalDylibResources> CODLogicalDylib;
78 typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
79 typedef std::list<CODLogicalDylib> LogicalDylibList;
82 /// @brief Handle to a set of loaded modules.
83 typedef typename LogicalDylibList::iterator ModuleSetHandleT;
85 /// @brief Construct a compile-on-demand layer instance.
86 CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
87 : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {}
89 /// @brief Add a module to the compile-on-demand layer.
90 template <typename ModuleSetT, typename MemoryManagerPtrT,
91 typename SymbolResolverPtrT>
92 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
93 MemoryManagerPtrT MemMgr,
94 SymbolResolverPtrT Resolver) {
96 assert(MemMgr == nullptr &&
97 "User supplied memory managers not supported with COD yet.");
99 LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
100 auto &LDLResources = LogicalDylibs.back().getDylibResources();
102 LDLResources.ExternalSymbolResolver =
103 [Resolver](const std::string &Name) {
104 return Resolver->findSymbol(Name);
107 LDLResources.Partitioner =
109 std::set<Function*> Partition;
110 Partition.insert(&F);
114 // Process each of the modules in this module set.
116 addLogicalModule(LogicalDylibs.back(),
117 std::shared_ptr<Module>(std::move(M)));
119 return std::prev(LogicalDylibs.end());
122 /// @brief Remove the module represented by the given handle.
124 /// This will remove all modules in the layers below that were derived from
125 /// the module represented by H.
126 void removeModuleSet(ModuleSetHandleT H) {
127 LogicalDylibs.erase(H);
130 /// @brief Search for the given named symbol.
131 /// @param Name The name of the symbol to search for.
132 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
133 /// @return A handle for the given named symbol, if it exists.
134 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
135 return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
138 /// @brief Get the address of a symbol provided by this layer, or some layer
140 JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
141 bool ExportedSymbolsOnly) {
142 return H->findSymbol(Name, ExportedSymbolsOnly);
147 void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module> SrcM) {
149 // Bump the linkage and rename any anonymous/privote members in SrcM to
150 // ensure that everything will resolve properly after we partition SrcM.
151 makeAllSymbolsExternallyAccessible(*SrcM);
153 // Create a logical module handle for SrcM within the logical dylib.
154 auto LMH = LD.createLogicalModule();
155 LD.getLogicalModuleResources(LMH).SourceModule = SrcM;
157 // Create the GVs-and-stubs module.
158 auto GVsAndStubsM = llvm::make_unique<Module>(
159 (SrcM->getName() + ".globals_and_stubs").str(),
161 GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
162 ValueToValueMapTy VMap;
164 // Process module and create stubs.
165 // We create the stubs before copying the global variables as we know the
166 // stubs won't refer to any globals (they only refer to their implementation
167 // pointer) so there's no ordering/value-mapping issues.
168 for (auto &F : *SrcM) {
170 // Skip declarations.
171 if (F.isDeclaration())
174 // For each definition: create a callback, a stub, and a function body
175 // pointer. Initialize the function body pointer to point at the callback,
176 // and set the callback to compile the function body.
177 auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
178 Function *StubF = cloneFunctionDecl(*GVsAndStubsM, F, &VMap);
179 GlobalVariable *FnBodyPtr =
180 createImplPointer(*StubF->getType(), *StubF->getParent(),
181 StubF->getName() + "$orc_addr",
182 createIRTypedAddress(*StubF->getFunctionType(),
183 CCInfo.getAddress()));
184 makeStub(*StubF, *FnBodyPtr);
185 CCInfo.setCompileAction(
186 [this, &LD, LMH, &F]() {
187 return this->extractAndCompile(LD, LMH, F);
191 // Now clone the global variable declarations.
192 GlobalDeclMaterializer GDMat(*GVsAndStubsM);
193 for (auto &GV : SrcM->globals())
194 if (!GV.isDeclaration())
195 cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
197 // Then clone the initializers.
198 for (auto &GV : SrcM->globals())
199 if (!GV.isDeclaration())
200 moveGlobalVariableInitializer(GV, VMap, &GDMat);
202 // Build a resolver for the stubs module and add it to the base layer.
203 auto GVsAndStubsResolver = createLambdaResolver(
204 [&LD](const std::string &Name) {
205 return LD.getDylibResources().ExternalSymbolResolver(Name);
207 [](const std::string &Name) {
208 return RuntimeDyld::SymbolInfo(nullptr);
211 std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
212 GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
214 BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
215 llvm::make_unique<SectionMemoryManager>(),
216 std::move(GVsAndStubsResolver));
217 LD.addToLogicalModule(LMH, GVsAndStubsH);
220 static std::string Mangle(StringRef Name, const DataLayout &DL) {
222 std::string MangledName;
224 raw_string_ostream MangledNameStream(MangledName);
225 M.getNameWithPrefix(MangledNameStream, Name);
230 TargetAddress extractAndCompile(CODLogicalDylib &LD,
231 LogicalModuleHandle LMH,
233 Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
235 // If F is a declaration we must already have compiled it.
236 if (F.isDeclaration())
239 // Grab the name of the function being called here.
240 std::string CalledFnName = Mangle(F.getName(), SrcM.getDataLayout());
242 const auto &Partition = LD.getDylibResources().Partitioner(F);
243 auto PartitionH = emitPartition(LD, LMH, Partition);
245 TargetAddress CalledAddr = 0;
246 for (auto *SubF : Partition) {
247 std::string FName(SubF->getName());
249 BaseLayer.findSymbolIn(PartitionH, Mangle(FName, SrcM.getDataLayout()),
252 BaseLayer.findSymbolIn(*LD.moduleHandlesBegin(LMH),
253 Mangle(FName + "$orc_addr",
254 SrcM.getDataLayout()),
256 assert(FnBodySym && "Couldn't find function body.");
257 assert(FnPtrSym && "Couldn't find function body pointer.");
259 auto FnBodyAddr = FnBodySym.getAddress();
260 void *FnPtrAddr = reinterpret_cast<void*>(
261 static_cast<uintptr_t>(FnPtrSym.getAddress()));
263 // If this is the function we're calling record the address so we can
264 // return it from this function.
266 CalledAddr = FnBodyAddr;
268 memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
274 BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
275 LogicalModuleHandle LMH,
276 const std::set<Function*> &Partition) {
277 Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
279 // Create the module.
280 std::string NewName(SrcM.getName());
281 for (auto *F : Partition) {
283 NewName += F->getName();
286 auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
287 M->setDataLayout(SrcM.getDataLayout());
288 ValueToValueMapTy VMap;
289 GlobalDeclMaterializer GDM(*M);
291 // Create decls in the new module.
292 for (auto *F : Partition)
293 cloneFunctionDecl(*M, *F, &VMap);
295 // Move the function bodies.
296 for (auto *F : Partition)
297 moveFunctionBody(*F, VMap);
299 // Create memory manager and symbol resolver.
300 auto MemMgr = llvm::make_unique<SectionMemoryManager>();
301 auto Resolver = createLambdaResolver(
302 [this, &LD, LMH](const std::string &Name) {
303 if (auto Symbol = LD.findSymbolInternally(LMH, Name))
304 return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
306 return LD.getDylibResources().ExternalSymbolResolver(Name);
308 [this, &LD, LMH](const std::string &Name) {
309 if (auto Symbol = LD.findSymbolInternally(LMH, Name))
310 return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
312 return RuntimeDyld::SymbolInfo(nullptr);
314 std::vector<std::unique_ptr<Module>> PartMSet;
315 PartMSet.push_back(std::move(M));
316 return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
317 std::move(Resolver));
320 BaseLayerT &BaseLayer;
321 CompileCallbackMgrT &CompileCallbackMgr;
322 LogicalDylibList LogicalDylibs;
325 } // End namespace orc.
326 } // End namespace llvm.
328 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H