CompileOnDemandLayer.h revision 309124
1//===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// JIT layer for breaking up modules and inserting callbacks to allow
11// individual functions to be compiled on demand.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
17
18#include "IndirectionUtils.h"
19#include "LambdaResolver.h"
20#include "LogicalDylib.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Transforms/Utils/Cloning.h"
24#include <list>
25#include <memory>
26#include <set>
27#include <utility>
28
29namespace llvm {
30namespace orc {
31
32/// @brief Compile-on-demand layer.
33///
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.
39template <typename BaseLayerT,
40          typename CompileCallbackMgrT = JITCompileCallbackManager,
41          typename IndirectStubsMgrT = IndirectStubsManager>
42class CompileOnDemandLayer {
43private:
44
45  template <typename MaterializerFtor>
46  class LambdaMaterializer final : public ValueMaterializer {
47  public:
48    LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
49    Value *materialize(Value *V) final { return M(V); }
50
51  private:
52    MaterializerFtor M;
53  };
54
55  template <typename MaterializerFtor>
56  LambdaMaterializer<MaterializerFtor>
57  createLambdaMaterializer(MaterializerFtor M) {
58    return LambdaMaterializer<MaterializerFtor>(std::move(M));
59  }
60
61  typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
62
63  // Provide type-erasure for the Modules and MemoryManagers.
64  template <typename ResourceT>
65  class ResourceOwner {
66  public:
67    ResourceOwner() = default;
68    ResourceOwner(const ResourceOwner&) = delete;
69    ResourceOwner& operator=(const ResourceOwner&) = delete;
70    virtual ~ResourceOwner() { }
71    virtual ResourceT& getResource() const = 0;
72  };
73
74  template <typename ResourceT, typename ResourcePtrT>
75  class ResourceOwnerImpl : public ResourceOwner<ResourceT> {
76  public:
77    ResourceOwnerImpl(ResourcePtrT ResourcePtr)
78      : ResourcePtr(std::move(ResourcePtr)) {}
79    ResourceT& getResource() const override { return *ResourcePtr; }
80  private:
81    ResourcePtrT ResourcePtr;
82  };
83
84  template <typename ResourceT, typename ResourcePtrT>
85  std::unique_ptr<ResourceOwner<ResourceT>>
86  wrapOwnership(ResourcePtrT ResourcePtr) {
87    typedef ResourceOwnerImpl<ResourceT, ResourcePtrT> RO;
88    return llvm::make_unique<RO>(std::move(ResourcePtr));
89  }
90
91  struct LogicalModuleResources {
92    std::unique_ptr<ResourceOwner<Module>> SourceModule;
93    std::set<const Function*> StubsToClone;
94    std::unique_ptr<IndirectStubsMgrT> StubsMgr;
95
96    LogicalModuleResources() = default;
97
98    // Explicit move constructor to make MSVC happy.
99    LogicalModuleResources(LogicalModuleResources &&Other)
100        : SourceModule(std::move(Other.SourceModule)),
101          StubsToClone(std::move(Other.StubsToClone)),
102          StubsMgr(std::move(Other.StubsMgr)) {}
103
104    // Explicit move assignment to make MSVC happy.
105    LogicalModuleResources& operator=(LogicalModuleResources &&Other) {
106      SourceModule = std::move(Other.SourceModule);
107      StubsToClone = std::move(Other.StubsToClone);
108      StubsMgr = std::move(Other.StubsMgr);
109      return *this;
110    }
111
112    JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
113      if (Name.endswith("$stub_ptr") && !ExportedSymbolsOnly) {
114        assert(!ExportedSymbolsOnly && "Stubs are never exported");
115        return StubsMgr->findPointer(Name.drop_back(9));
116      }
117      return StubsMgr->findStub(Name, ExportedSymbolsOnly);
118    }
119
120  };
121
122  struct LogicalDylibResources {
123    typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
124      SymbolResolverFtor;
125
126    typedef std::function<typename BaseLayerT::ModuleSetHandleT(
127                            BaseLayerT&,
128                            std::unique_ptr<Module>,
129                            std::unique_ptr<RuntimeDyld::SymbolResolver>)>
130      ModuleAdderFtor;
131
132    LogicalDylibResources() = default;
133
134    // Explicit move constructor to make MSVC happy.
135    LogicalDylibResources(LogicalDylibResources &&Other)
136      : ExternalSymbolResolver(std::move(Other.ExternalSymbolResolver)),
137        MemMgr(std::move(Other.MemMgr)),
138        ModuleAdder(std::move(Other.ModuleAdder)) {}
139
140    // Explicit move assignment operator to make MSVC happy.
141    LogicalDylibResources& operator=(LogicalDylibResources &&Other) {
142      ExternalSymbolResolver = std::move(Other.ExternalSymbolResolver);
143      MemMgr = std::move(Other.MemMgr);
144      ModuleAdder = std::move(Other.ModuleAdder);
145      return *this;
146    }
147
148    std::unique_ptr<RuntimeDyld::SymbolResolver> ExternalSymbolResolver;
149    std::unique_ptr<ResourceOwner<RuntimeDyld::MemoryManager>> MemMgr;
150    ModuleAdderFtor ModuleAdder;
151  };
152
153  typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
154                       LogicalDylibResources> CODLogicalDylib;
155
156  typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
157  typedef std::list<CODLogicalDylib> LogicalDylibList;
158
159public:
160
161  /// @brief Handle to a set of loaded modules.
162  typedef typename LogicalDylibList::iterator ModuleSetHandleT;
163
164  /// @brief Module partitioning functor.
165  typedef std::function<std::set<Function*>(Function&)> PartitioningFtor;
166
167  /// @brief Builder for IndirectStubsManagers.
168  typedef std::function<std::unique_ptr<IndirectStubsMgrT>()>
169    IndirectStubsManagerBuilderT;
170
171  /// @brief Construct a compile-on-demand layer instance.
172  CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
173                       CompileCallbackMgrT &CallbackMgr,
174                       IndirectStubsManagerBuilderT CreateIndirectStubsManager,
175                       bool CloneStubsIntoPartitions = true)
176      : BaseLayer(BaseLayer), Partition(std::move(Partition)),
177        CompileCallbackMgr(CallbackMgr),
178        CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
179        CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
180
181  /// @brief Add a module to the compile-on-demand layer.
182  template <typename ModuleSetT, typename MemoryManagerPtrT,
183            typename SymbolResolverPtrT>
184  ModuleSetHandleT addModuleSet(ModuleSetT Ms,
185                                MemoryManagerPtrT MemMgr,
186                                SymbolResolverPtrT Resolver) {
187
188    LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
189    auto &LDResources = LogicalDylibs.back().getDylibResources();
190
191    LDResources.ExternalSymbolResolver = std::move(Resolver);
192
193    auto &MemMgrRef = *MemMgr;
194    LDResources.MemMgr =
195      wrapOwnership<RuntimeDyld::MemoryManager>(std::move(MemMgr));
196
197    LDResources.ModuleAdder =
198      [&MemMgrRef](BaseLayerT &B, std::unique_ptr<Module> M,
199                   std::unique_ptr<RuntimeDyld::SymbolResolver> R) {
200        std::vector<std::unique_ptr<Module>> Ms;
201        Ms.push_back(std::move(M));
202        return B.addModuleSet(std::move(Ms), &MemMgrRef, std::move(R));
203      };
204
205    // Process each of the modules in this module set.
206    for (auto &M : Ms)
207      addLogicalModule(LogicalDylibs.back(), std::move(M));
208
209    return std::prev(LogicalDylibs.end());
210  }
211
212  /// @brief Remove the module represented by the given handle.
213  ///
214  ///   This will remove all modules in the layers below that were derived from
215  /// the module represented by H.
216  void removeModuleSet(ModuleSetHandleT H) {
217    LogicalDylibs.erase(H);
218  }
219
220  /// @brief Search for the given named symbol.
221  /// @param Name The name of the symbol to search for.
222  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
223  /// @return A handle for the given named symbol, if it exists.
224  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
225    for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
226         LDI != LDE; ++LDI)
227      if (auto Symbol = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
228        return Symbol;
229    return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
230  }
231
232  /// @brief Get the address of a symbol provided by this layer, or some layer
233  ///        below this one.
234  JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
235                         bool ExportedSymbolsOnly) {
236    return H->findSymbol(Name, ExportedSymbolsOnly);
237  }
238
239private:
240
241  template <typename ModulePtrT>
242  void addLogicalModule(CODLogicalDylib &LD, ModulePtrT SrcMPtr) {
243
244    // Bump the linkage and rename any anonymous/privote members in SrcM to
245    // ensure that everything will resolve properly after we partition SrcM.
246    makeAllSymbolsExternallyAccessible(*SrcMPtr);
247
248    // Create a logical module handle for SrcM within the logical dylib.
249    auto LMH = LD.createLogicalModule();
250    auto &LMResources =  LD.getLogicalModuleResources(LMH);
251
252    LMResources.SourceModule = wrapOwnership<Module>(std::move(SrcMPtr));
253
254    Module &SrcM = LMResources.SourceModule->getResource();
255
256    // Create stub functions.
257    const DataLayout &DL = SrcM.getDataLayout();
258    {
259      typename IndirectStubsMgrT::StubInitsMap StubInits;
260      for (auto &F : SrcM) {
261        // Skip declarations.
262        if (F.isDeclaration())
263          continue;
264
265        // Record all functions defined by this module.
266        if (CloneStubsIntoPartitions)
267          LMResources.StubsToClone.insert(&F);
268
269        // Create a callback, associate it with the stub for the function,
270        // and set the compile action to compile the partition containing the
271        // function.
272        auto CCInfo = CompileCallbackMgr.getCompileCallback();
273        StubInits[mangle(F.getName(), DL)] =
274          std::make_pair(CCInfo.getAddress(),
275                         JITSymbolBase::flagsFromGlobalValue(F));
276        CCInfo.setCompileAction([this, &LD, LMH, &F]() {
277          return this->extractAndCompile(LD, LMH, F);
278        });
279      }
280
281      LMResources.StubsMgr = CreateIndirectStubsManager();
282      auto EC = LMResources.StubsMgr->createStubs(StubInits);
283      (void)EC;
284      // FIXME: This should be propagated back to the user. Stub creation may
285      //        fail for remote JITs.
286      assert(!EC && "Error generating stubs");
287    }
288
289    // If this module doesn't contain any globals or aliases we can bail out
290    // early and avoid the overhead of creating and managing an empty globals
291    // module.
292    if (SrcM.global_empty() && SrcM.alias_empty())
293      return;
294
295    // Create the GlobalValues module.
296    auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
297                                          SrcM.getContext());
298    GVsM->setDataLayout(DL);
299
300    ValueToValueMapTy VMap;
301
302    // Clone global variable decls.
303    for (auto &GV : SrcM.globals())
304      if (!GV.isDeclaration() && !VMap.count(&GV))
305        cloneGlobalVariableDecl(*GVsM, GV, &VMap);
306
307    // And the aliases.
308    for (auto &A : SrcM.aliases())
309      if (!VMap.count(&A))
310        cloneGlobalAliasDecl(*GVsM, A, VMap);
311
312    // Now we need to clone the GV and alias initializers.
313
314    // Initializers may refer to functions declared (but not defined) in this
315    // module. Build a materializer to clone decls on demand.
316    auto Materializer = createLambdaMaterializer(
317      [this, &GVsM, &LMResources](Value *V) -> Value* {
318        if (auto *F = dyn_cast<Function>(V)) {
319          // Decls in the original module just get cloned.
320          if (F->isDeclaration())
321            return cloneFunctionDecl(*GVsM, *F);
322
323          // Definitions in the original module (which we have emitted stubs
324          // for at this point) get turned into a constant alias to the stub
325          // instead.
326          const DataLayout &DL = GVsM->getDataLayout();
327          std::string FName = mangle(F->getName(), DL);
328          auto StubSym = LMResources.StubsMgr->findStub(FName, false);
329          unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
330          ConstantInt *StubAddr =
331            ConstantInt::get(GVsM->getContext(),
332                             APInt(PtrBitWidth, StubSym.getAddress()));
333          Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
334                                                 StubAddr, F->getType());
335          return GlobalAlias::create(F->getFunctionType(),
336                                     F->getType()->getAddressSpace(),
337                                     F->getLinkage(), F->getName(),
338                                     Init, GVsM.get());
339        }
340        // else....
341        return nullptr;
342      });
343
344    // Clone the global variable initializers.
345    for (auto &GV : SrcM.globals())
346      if (!GV.isDeclaration())
347        moveGlobalVariableInitializer(GV, VMap, &Materializer);
348
349    // Clone the global alias initializers.
350    for (auto &A : SrcM.aliases()) {
351      auto *NewA = cast<GlobalAlias>(VMap[&A]);
352      assert(NewA && "Alias not cloned?");
353      Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
354                             &Materializer);
355      NewA->setAliasee(cast<Constant>(Init));
356    }
357
358    // Build a resolver for the globals module and add it to the base layer.
359    auto GVsResolver = createLambdaResolver(
360        [&LD, LMH](const std::string &Name) {
361          auto &LMResources = LD.getLogicalModuleResources(LMH);
362          if (auto Sym = LMResources.StubsMgr->findStub(Name, false))
363            return Sym.toRuntimeDyldSymbol();
364          auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
365          return LDResolver->findSymbolInLogicalDylib(Name);
366        },
367        [&LD](const std::string &Name) {
368          auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
369          return LDResolver->findSymbol(Name);
370        });
371
372    auto GVsH = LD.getDylibResources().ModuleAdder(BaseLayer, std::move(GVsM),
373                                                   std::move(GVsResolver));
374    LD.addToLogicalModule(LMH, GVsH);
375  }
376
377  static std::string mangle(StringRef Name, const DataLayout &DL) {
378    std::string MangledName;
379    {
380      raw_string_ostream MangledNameStream(MangledName);
381      Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
382    }
383    return MangledName;
384  }
385
386  TargetAddress extractAndCompile(CODLogicalDylib &LD,
387                                  LogicalModuleHandle LMH,
388                                  Function &F) {
389    auto &LMResources = LD.getLogicalModuleResources(LMH);
390    Module &SrcM = LMResources.SourceModule->getResource();
391
392    // If F is a declaration we must already have compiled it.
393    if (F.isDeclaration())
394      return 0;
395
396    // Grab the name of the function being called here.
397    std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
398
399    auto Part = Partition(F);
400    auto PartH = emitPartition(LD, LMH, Part);
401
402    TargetAddress CalledAddr = 0;
403    for (auto *SubF : Part) {
404      std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
405      auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
406      assert(FnBodySym && "Couldn't find function body.");
407
408      TargetAddress FnBodyAddr = FnBodySym.getAddress();
409
410      // If this is the function we're calling record the address so we can
411      // return it from this function.
412      if (SubF == &F)
413        CalledAddr = FnBodyAddr;
414
415      // Update the function body pointer for the stub.
416      if (auto EC = LMResources.StubsMgr->updatePointer(FnName, FnBodyAddr))
417        return 0;
418    }
419
420    return CalledAddr;
421  }
422
423  template <typename PartitionT>
424  BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
425                                          LogicalModuleHandle LMH,
426                                          const PartitionT &Part) {
427    auto &LMResources = LD.getLogicalModuleResources(LMH);
428    Module &SrcM = LMResources.SourceModule->getResource();
429
430    // Create the module.
431    std::string NewName = SrcM.getName();
432    for (auto *F : Part) {
433      NewName += ".";
434      NewName += F->getName();
435    }
436
437    auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
438    M->setDataLayout(SrcM.getDataLayout());
439    ValueToValueMapTy VMap;
440
441    auto Materializer = createLambdaMaterializer([this, &LMResources, &M,
442                                                  &VMap](Value *V) -> Value * {
443      if (auto *GV = dyn_cast<GlobalVariable>(V))
444        return cloneGlobalVariableDecl(*M, *GV);
445
446      if (auto *F = dyn_cast<Function>(V)) {
447        // Check whether we want to clone an available_externally definition.
448        if (!LMResources.StubsToClone.count(F))
449          return cloneFunctionDecl(*M, *F);
450
451        // Ok - we want an inlinable stub. For that to work we need a decl
452        // for the stub pointer.
453        auto *StubPtr = createImplPointer(*F->getType(), *M,
454                                          F->getName() + "$stub_ptr", nullptr);
455        auto *ClonedF = cloneFunctionDecl(*M, *F);
456        makeStub(*ClonedF, *StubPtr);
457        ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
458        ClonedF->addFnAttr(Attribute::AlwaysInline);
459        return ClonedF;
460      }
461
462      if (auto *A = dyn_cast<GlobalAlias>(V)) {
463        auto *Ty = A->getValueType();
464        if (Ty->isFunctionTy())
465          return Function::Create(cast<FunctionType>(Ty),
466                                  GlobalValue::ExternalLinkage, A->getName(),
467                                  M.get());
468
469        return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
470                                  nullptr, A->getName(), nullptr,
471                                  GlobalValue::NotThreadLocal,
472                                  A->getType()->getAddressSpace());
473      }
474
475      return nullptr;
476    });
477
478    // Create decls in the new module.
479    for (auto *F : Part)
480      cloneFunctionDecl(*M, *F, &VMap);
481
482    // Move the function bodies.
483    for (auto *F : Part)
484      moveFunctionBody(*F, VMap, &Materializer);
485
486    // Create memory manager and symbol resolver.
487    auto Resolver = createLambdaResolver(
488        [this, &LD, LMH](const std::string &Name) {
489          if (auto Sym = LD.findSymbolInternally(LMH, Name))
490            return Sym.toRuntimeDyldSymbol();
491          auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
492          return LDResolver->findSymbolInLogicalDylib(Name);
493        },
494        [this, &LD](const std::string &Name) {
495          auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver;
496          return LDResolver->findSymbol(Name);
497        });
498
499    return LD.getDylibResources().ModuleAdder(BaseLayer, std::move(M),
500                                              std::move(Resolver));
501  }
502
503  BaseLayerT &BaseLayer;
504  PartitioningFtor Partition;
505  CompileCallbackMgrT &CompileCallbackMgr;
506  IndirectStubsManagerBuilderT CreateIndirectStubsManager;
507
508  LogicalDylibList LogicalDylibs;
509  bool CloneStubsIntoPartitions;
510};
511
512} // End namespace orc.
513} // End namespace llvm.
514
515#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
516