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,
40 typename CompileCallbackMgrT = JITCompileCallbackManagerBase,
41 typename IndirectStubsMgrT = IndirectStubsManagerBase>
42 class CompileOnDemandLayer {
45 template <typename MaterializerFtor>
46 class LambdaMaterializer : public ValueMaterializer {
48 LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
49 Value* materializeValueFor(Value *V) final {
56 template <typename MaterializerFtor>
57 LambdaMaterializer<MaterializerFtor>
58 createLambdaMaterializer(MaterializerFtor M) {
59 return LambdaMaterializer<MaterializerFtor>(std::move(M));
62 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
64 struct LogicalModuleResources {
65 std::shared_ptr<Module> SourceModule;
66 std::set<const Function*> StubsToClone;
67 std::unique_ptr<IndirectStubsMgrT> StubsMgr;
69 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
70 if (Name.endswith("$stub_ptr") && !ExportedSymbolsOnly) {
71 assert(!ExportedSymbolsOnly && "Stubs are never exported");
72 return StubsMgr->findPointer(Name.drop_back(9));
74 return StubsMgr->findStub(Name, ExportedSymbolsOnly);
79 struct LogicalDylibResources {
80 typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
82 SymbolResolverFtor ExternalSymbolResolver;
85 typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
86 LogicalDylibResources> CODLogicalDylib;
88 typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
89 typedef std::list<CODLogicalDylib> LogicalDylibList;
93 /// @brief Handle to a set of loaded modules.
94 typedef typename LogicalDylibList::iterator ModuleSetHandleT;
96 /// @brief Module partitioning functor.
97 typedef std::function<std::set<Function*>(Function&)> PartitioningFtor;
99 /// @brief Builder for IndirectStubsManagers.
100 typedef std::function<std::unique_ptr<IndirectStubsMgrT>()>
101 IndirectStubsManagerBuilderT;
103 /// @brief Construct a compile-on-demand layer instance.
104 CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
105 CompileCallbackMgrT &CallbackMgr,
106 IndirectStubsManagerBuilderT CreateIndirectStubsManager,
107 bool CloneStubsIntoPartitions = true)
108 : BaseLayer(BaseLayer), Partition(Partition),
109 CompileCallbackMgr(CallbackMgr),
110 CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
111 CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
113 /// @brief Add a module to the compile-on-demand layer.
114 template <typename ModuleSetT, typename MemoryManagerPtrT,
115 typename SymbolResolverPtrT>
116 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
117 MemoryManagerPtrT MemMgr,
118 SymbolResolverPtrT Resolver) {
120 assert(MemMgr == nullptr &&
121 "User supplied memory managers not supported with COD yet.");
123 LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
124 auto &LDResources = LogicalDylibs.back().getDylibResources();
126 LDResources.ExternalSymbolResolver =
127 [Resolver](const std::string &Name) {
128 return Resolver->findSymbol(Name);
131 // Process each of the modules in this module set.
133 addLogicalModule(LogicalDylibs.back(),
134 std::shared_ptr<Module>(std::move(M)));
136 return std::prev(LogicalDylibs.end());
139 /// @brief Remove the module represented by the given handle.
141 /// This will remove all modules in the layers below that were derived from
142 /// the module represented by H.
143 void removeModuleSet(ModuleSetHandleT H) {
144 LogicalDylibs.erase(H);
147 /// @brief Search for the given named symbol.
148 /// @param Name The name of the symbol to search for.
149 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
150 /// @return A handle for the given named symbol, if it exists.
151 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
152 for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
154 if (auto Symbol = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
159 /// @brief Get the address of a symbol provided by this layer, or some layer
161 JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
162 bool ExportedSymbolsOnly) {
163 return H->findSymbol(Name, ExportedSymbolsOnly);
168 void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module> SrcM) {
170 // Bump the linkage and rename any anonymous/privote members in SrcM to
171 // ensure that everything will resolve properly after we partition SrcM.
172 makeAllSymbolsExternallyAccessible(*SrcM);
174 // Create a logical module handle for SrcM within the logical dylib.
175 auto LMH = LD.createLogicalModule();
176 auto &LMResources = LD.getLogicalModuleResources(LMH);
178 LMResources.SourceModule = SrcM;
180 // Create the GlobalValues module.
181 const DataLayout &DL = SrcM->getDataLayout();
182 auto GVsM = llvm::make_unique<Module>((SrcM->getName() + ".globals").str(),
184 GVsM->setDataLayout(DL);
186 // Create function stubs.
187 ValueToValueMapTy VMap;
189 typename IndirectStubsMgrT::StubInitsMap StubInits;
190 for (auto &F : *SrcM) {
191 // Skip declarations.
192 if (F.isDeclaration())
195 // Record all functions defined by this module.
196 if (CloneStubsIntoPartitions)
197 LMResources.StubsToClone.insert(&F);
199 // Create a callback, associate it with the stub for the function,
200 // and set the compile action to compile the partition containing the
202 auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
203 StubInits[mangle(F.getName(), DL)] =
204 std::make_pair(CCInfo.getAddress(),
205 JITSymbolBase::flagsFromGlobalValue(F));
206 CCInfo.setCompileAction(
207 [this, &LD, LMH, &F]() {
208 return this->extractAndCompile(LD, LMH, F);
212 LMResources.StubsMgr = CreateIndirectStubsManager();
213 auto EC = LMResources.StubsMgr->init(StubInits);
215 // FIXME: This should be propagated back to the user. Stub creation may
216 // fail for remote JITs.
217 assert(!EC && "Error generating stubs");
220 // Clone global variable decls.
221 for (auto &GV : SrcM->globals())
222 if (!GV.isDeclaration() && !VMap.count(&GV))
223 cloneGlobalVariableDecl(*GVsM, GV, &VMap);
226 for (auto &A : SrcM->aliases())
228 cloneGlobalAliasDecl(*GVsM, A, VMap);
230 // Now we need to clone the GV and alias initializers.
232 // Initializers may refer to functions declared (but not defined) in this
233 // module. Build a materializer to clone decls on demand.
234 auto Materializer = createLambdaMaterializer(
235 [this, &GVsM, &LMResources](Value *V) -> Value* {
236 if (auto *F = dyn_cast<Function>(V)) {
237 // Decls in the original module just get cloned.
238 if (F->isDeclaration())
239 return cloneFunctionDecl(*GVsM, *F);
241 // Definitions in the original module (which we have emitted stubs
242 // for at this point) get turned into a constant alias to the stub
244 const DataLayout &DL = GVsM->getDataLayout();
245 std::string FName = mangle(F->getName(), DL);
246 auto StubSym = LMResources.StubsMgr->findStub(FName, false);
247 unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
248 ConstantInt *StubAddr =
249 ConstantInt::get(GVsM->getContext(),
250 APInt(PtrBitWidth, StubSym.getAddress()));
251 Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
252 StubAddr, F->getType());
253 return GlobalAlias::create(F->getFunctionType(),
254 F->getType()->getAddressSpace(),
255 F->getLinkage(), F->getName(),
262 // Clone the global variable initializers.
263 for (auto &GV : SrcM->globals())
264 if (!GV.isDeclaration())
265 moveGlobalVariableInitializer(GV, VMap, &Materializer);
267 // Clone the global alias initializers.
268 for (auto &A : SrcM->aliases()) {
269 auto *NewA = cast<GlobalAlias>(VMap[&A]);
270 assert(NewA && "Alias not cloned?");
271 Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
273 NewA->setAliasee(cast<Constant>(Init));
276 // Build a resolver for the globals module and add it to the base layer.
277 auto GVsResolver = createLambdaResolver(
278 [&LD, LMH](const std::string &Name) {
279 auto &LMResources = LD.getLogicalModuleResources(LMH);
280 if (auto Sym = LMResources.StubsMgr->findStub(Name, false))
281 return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
282 return LD.getDylibResources().ExternalSymbolResolver(Name);
284 [](const std::string &Name) {
285 return RuntimeDyld::SymbolInfo(nullptr);
288 std::vector<std::unique_ptr<Module>> GVsMSet;
289 GVsMSet.push_back(std::move(GVsM));
291 BaseLayer.addModuleSet(std::move(GVsMSet),
292 llvm::make_unique<SectionMemoryManager>(),
293 std::move(GVsResolver));
294 LD.addToLogicalModule(LMH, GVsH);
297 static std::string mangle(StringRef Name, const DataLayout &DL) {
298 std::string MangledName;
300 raw_string_ostream MangledNameStream(MangledName);
301 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
306 TargetAddress extractAndCompile(CODLogicalDylib &LD,
307 LogicalModuleHandle LMH,
309 auto &LMResources = LD.getLogicalModuleResources(LMH);
310 Module &SrcM = *LMResources.SourceModule;
312 // If F is a declaration we must already have compiled it.
313 if (F.isDeclaration())
316 // Grab the name of the function being called here.
317 std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
319 auto Part = Partition(F);
320 auto PartH = emitPartition(LD, LMH, Part);
322 TargetAddress CalledAddr = 0;
323 for (auto *SubF : Part) {
324 std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
325 auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
326 assert(FnBodySym && "Couldn't find function body.");
328 TargetAddress FnBodyAddr = FnBodySym.getAddress();
330 // If this is the function we're calling record the address so we can
331 // return it from this function.
333 CalledAddr = FnBodyAddr;
335 // Update the function body pointer for the stub.
336 if (auto EC = LMResources.StubsMgr->updatePointer(FnName, FnBodyAddr))
343 template <typename PartitionT>
344 BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
345 LogicalModuleHandle LMH,
346 const PartitionT &Part) {
347 auto &LMResources = LD.getLogicalModuleResources(LMH);
348 Module &SrcM = *LMResources.SourceModule;
350 // Create the module.
351 std::string NewName = SrcM.getName();
352 for (auto *F : Part) {
354 NewName += F->getName();
357 auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
358 M->setDataLayout(SrcM.getDataLayout());
359 ValueToValueMapTy VMap;
361 auto Materializer = createLambdaMaterializer(
362 [this, &LMResources, &M, &VMap](Value *V) -> Value* {
363 if (auto *GV = dyn_cast<GlobalVariable>(V)) {
364 return cloneGlobalVariableDecl(*M, *GV);
365 } else if (auto *F = dyn_cast<Function>(V)) {
366 // Check whether we want to clone an available_externally definition.
367 if (LMResources.StubsToClone.count(F)) {
368 // Ok - we want an inlinable stub. For that to work we need a decl
369 // for the stub pointer.
370 auto *StubPtr = createImplPointer(*F->getType(), *M,
371 F->getName() + "$stub_ptr",
373 auto *ClonedF = cloneFunctionDecl(*M, *F);
374 makeStub(*ClonedF, *StubPtr);
375 ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
376 ClonedF->addFnAttr(Attribute::AlwaysInline);
380 return cloneFunctionDecl(*M, *F);
381 } else if (auto *A = dyn_cast<GlobalAlias>(V)) {
382 auto *PTy = cast<PointerType>(A->getType());
383 if (PTy->getElementType()->isFunctionTy())
384 return Function::Create(cast<FunctionType>(PTy->getElementType()),
385 GlobalValue::ExternalLinkage,
386 A->getName(), M.get());
388 return new GlobalVariable(*M, PTy->getElementType(), false,
389 GlobalValue::ExternalLinkage,
390 nullptr, A->getName(), nullptr,
391 GlobalValue::NotThreadLocal,
392 PTy->getAddressSpace());
398 // Create decls in the new module.
400 cloneFunctionDecl(*M, *F, &VMap);
402 // Move the function bodies.
404 moveFunctionBody(*F, VMap, &Materializer);
406 // Create memory manager and symbol resolver.
407 auto MemMgr = llvm::make_unique<SectionMemoryManager>();
408 auto Resolver = createLambdaResolver(
409 [this, &LD, LMH](const std::string &Name) {
410 if (auto Symbol = LD.findSymbolInternally(LMH, Name))
411 return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
413 return LD.getDylibResources().ExternalSymbolResolver(Name);
415 [this, &LD, LMH](const std::string &Name) {
416 if (auto Symbol = LD.findSymbolInternally(LMH, Name))
417 return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
419 return RuntimeDyld::SymbolInfo(nullptr);
421 std::vector<std::unique_ptr<Module>> PartMSet;
422 PartMSet.push_back(std::move(M));
423 return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
424 std::move(Resolver));
427 BaseLayerT &BaseLayer;
428 PartitioningFtor Partition;
429 CompileCallbackMgrT &CompileCallbackMgr;
430 IndirectStubsManagerBuilderT CreateIndirectStubsManager;
432 LogicalDylibList LogicalDylibs;
433 bool CloneStubsIntoPartitions;
436 } // End namespace orc.
437 } // End namespace llvm.
439 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H