CompileOnDemandLayer.h revision 296417
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/Transforms/Utils/Cloning.h"
23#include <list>
24#include <memory>
25#include <set>
26
27#include "llvm/Support/Debug.h"
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 *materializeDeclFor(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    SymbolResolverFtor 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(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 =
192      [Resolver](const std::string &Name) {
193        return Resolver->findSymbol(Name);
194      };
195
196    auto &MemMgrRef = *MemMgr;
197    LDResources.MemMgr =
198      wrapOwnership<RuntimeDyld::MemoryManager>(std::move(MemMgr));
199
200    LDResources.ModuleAdder =
201      [&MemMgrRef](BaseLayerT &B, std::unique_ptr<Module> M,
202                   std::unique_ptr<RuntimeDyld::SymbolResolver> R) {
203        std::vector<std::unique_ptr<Module>> Ms;
204        Ms.push_back(std::move(M));
205        return B.addModuleSet(std::move(Ms), &MemMgrRef, std::move(R));
206      };
207
208    // Process each of the modules in this module set.
209    for (auto &M : Ms)
210      addLogicalModule(LogicalDylibs.back(), std::move(M));
211
212    return std::prev(LogicalDylibs.end());
213  }
214
215  /// @brief Remove the module represented by the given handle.
216  ///
217  ///   This will remove all modules in the layers below that were derived from
218  /// the module represented by H.
219  void removeModuleSet(ModuleSetHandleT H) {
220    LogicalDylibs.erase(H);
221  }
222
223  /// @brief Search for the given named symbol.
224  /// @param Name The name of the symbol to search for.
225  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
226  /// @return A handle for the given named symbol, if it exists.
227  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
228    for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
229         LDI != LDE; ++LDI)
230      if (auto Symbol = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
231        return Symbol;
232    return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
233  }
234
235  /// @brief Get the address of a symbol provided by this layer, or some layer
236  ///        below this one.
237  JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
238                         bool ExportedSymbolsOnly) {
239    return H->findSymbol(Name, ExportedSymbolsOnly);
240  }
241
242private:
243
244  template <typename ModulePtrT>
245  void addLogicalModule(CODLogicalDylib &LD, ModulePtrT SrcMPtr) {
246
247    // Bump the linkage and rename any anonymous/privote members in SrcM to
248    // ensure that everything will resolve properly after we partition SrcM.
249    makeAllSymbolsExternallyAccessible(*SrcMPtr);
250
251    // Create a logical module handle for SrcM within the logical dylib.
252    auto LMH = LD.createLogicalModule();
253    auto &LMResources =  LD.getLogicalModuleResources(LMH);
254
255    LMResources.SourceModule = wrapOwnership<Module>(std::move(SrcMPtr));
256
257    Module &SrcM = LMResources.SourceModule->getResource();
258
259    // Create the GlobalValues module.
260    const DataLayout &DL = SrcM.getDataLayout();
261    auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
262                                          SrcM.getContext());
263    GVsM->setDataLayout(DL);
264
265    // Create function stubs.
266    ValueToValueMapTy VMap;
267    {
268      typename IndirectStubsMgrT::StubInitsMap StubInits;
269      for (auto &F : SrcM) {
270        // Skip declarations.
271        if (F.isDeclaration())
272          continue;
273
274        // Record all functions defined by this module.
275        if (CloneStubsIntoPartitions)
276          LMResources.StubsToClone.insert(&F);
277
278        // Create a callback, associate it with the stub for the function,
279        // and set the compile action to compile the partition containing the
280        // function.
281        auto CCInfo = CompileCallbackMgr.getCompileCallback();
282        StubInits[mangle(F.getName(), DL)] =
283          std::make_pair(CCInfo.getAddress(),
284                         JITSymbolBase::flagsFromGlobalValue(F));
285        CCInfo.setCompileAction([this, &LD, LMH, &F]() {
286          return this->extractAndCompile(LD, LMH, F);
287        });
288      }
289
290      LMResources.StubsMgr = CreateIndirectStubsManager();
291      auto EC = LMResources.StubsMgr->createStubs(StubInits);
292      (void)EC;
293      // FIXME: This should be propagated back to the user. Stub creation may
294      //        fail for remote JITs.
295      assert(!EC && "Error generating stubs");
296    }
297
298    // Clone global variable decls.
299    for (auto &GV : SrcM.globals())
300      if (!GV.isDeclaration() && !VMap.count(&GV))
301        cloneGlobalVariableDecl(*GVsM, GV, &VMap);
302
303    // And the aliases.
304    for (auto &A : SrcM.aliases())
305      if (!VMap.count(&A))
306        cloneGlobalAliasDecl(*GVsM, A, VMap);
307
308    // Now we need to clone the GV and alias initializers.
309
310    // Initializers may refer to functions declared (but not defined) in this
311    // module. Build a materializer to clone decls on demand.
312    auto Materializer = createLambdaMaterializer(
313      [this, &GVsM, &LMResources](Value *V) -> Value* {
314        if (auto *F = dyn_cast<Function>(V)) {
315          // Decls in the original module just get cloned.
316          if (F->isDeclaration())
317            return cloneFunctionDecl(*GVsM, *F);
318
319          // Definitions in the original module (which we have emitted stubs
320          // for at this point) get turned into a constant alias to the stub
321          // instead.
322          const DataLayout &DL = GVsM->getDataLayout();
323          std::string FName = mangle(F->getName(), DL);
324          auto StubSym = LMResources.StubsMgr->findStub(FName, false);
325          unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
326          ConstantInt *StubAddr =
327            ConstantInt::get(GVsM->getContext(),
328                             APInt(PtrBitWidth, StubSym.getAddress()));
329          Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
330                                                 StubAddr, F->getType());
331          return GlobalAlias::create(F->getFunctionType(),
332                                     F->getType()->getAddressSpace(),
333                                     F->getLinkage(), F->getName(),
334                                     Init, GVsM.get());
335        }
336        // else....
337        return nullptr;
338      });
339
340    // Clone the global variable initializers.
341    for (auto &GV : SrcM.globals())
342      if (!GV.isDeclaration())
343        moveGlobalVariableInitializer(GV, VMap, &Materializer);
344
345    // Clone the global alias initializers.
346    for (auto &A : SrcM.aliases()) {
347      auto *NewA = cast<GlobalAlias>(VMap[&A]);
348      assert(NewA && "Alias not cloned?");
349      Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
350                             &Materializer);
351      NewA->setAliasee(cast<Constant>(Init));
352    }
353
354    // Build a resolver for the globals module and add it to the base layer.
355    auto GVsResolver = createLambdaResolver(
356        [&LD, LMH](const std::string &Name) {
357          auto &LMResources = LD.getLogicalModuleResources(LMH);
358          if (auto Sym = LMResources.StubsMgr->findStub(Name, false))
359            return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
360          return LD.getDylibResources().ExternalSymbolResolver(Name);
361        },
362        [](const std::string &Name) {
363          return RuntimeDyld::SymbolInfo(nullptr);
364        });
365
366    auto GVsH =
367      LD.getDylibResources().ModuleAdder(BaseLayer, std::move(GVsM),
368				         std::move(GVsResolver));
369    LD.addToLogicalModule(LMH, GVsH);
370  }
371
372  static std::string mangle(StringRef Name, const DataLayout &DL) {
373    std::string MangledName;
374    {
375      raw_string_ostream MangledNameStream(MangledName);
376      Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
377    }
378    return MangledName;
379  }
380
381  TargetAddress extractAndCompile(CODLogicalDylib &LD,
382                                  LogicalModuleHandle LMH,
383                                  Function &F) {
384    auto &LMResources = LD.getLogicalModuleResources(LMH);
385    Module &SrcM = LMResources.SourceModule->getResource();
386
387    // If F is a declaration we must already have compiled it.
388    if (F.isDeclaration())
389      return 0;
390
391    // Grab the name of the function being called here.
392    std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
393
394    auto Part = Partition(F);
395    auto PartH = emitPartition(LD, LMH, Part);
396
397    TargetAddress CalledAddr = 0;
398    for (auto *SubF : Part) {
399      std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
400      auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
401      assert(FnBodySym && "Couldn't find function body.");
402
403      TargetAddress FnBodyAddr = FnBodySym.getAddress();
404
405      // If this is the function we're calling record the address so we can
406      // return it from this function.
407      if (SubF == &F)
408        CalledAddr = FnBodyAddr;
409
410      // Update the function body pointer for the stub.
411      if (auto EC = LMResources.StubsMgr->updatePointer(FnName, FnBodyAddr))
412        return 0;
413    }
414
415    return CalledAddr;
416  }
417
418  template <typename PartitionT>
419  BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
420                                          LogicalModuleHandle LMH,
421                                          const PartitionT &Part) {
422    auto &LMResources = LD.getLogicalModuleResources(LMH);
423    Module &SrcM = LMResources.SourceModule->getResource();
424
425    // Create the module.
426    std::string NewName = SrcM.getName();
427    for (auto *F : Part) {
428      NewName += ".";
429      NewName += F->getName();
430    }
431
432    auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
433    M->setDataLayout(SrcM.getDataLayout());
434    ValueToValueMapTy VMap;
435
436    auto Materializer = createLambdaMaterializer([this, &LMResources, &M,
437                                                  &VMap](Value *V) -> Value * {
438      if (auto *GV = dyn_cast<GlobalVariable>(V))
439        return cloneGlobalVariableDecl(*M, *GV);
440
441      if (auto *F = dyn_cast<Function>(V)) {
442        // Check whether we want to clone an available_externally definition.
443        if (!LMResources.StubsToClone.count(F))
444          return cloneFunctionDecl(*M, *F);
445
446        // Ok - we want an inlinable stub. For that to work we need a decl
447        // for the stub pointer.
448        auto *StubPtr = createImplPointer(*F->getType(), *M,
449                                          F->getName() + "$stub_ptr", nullptr);
450        auto *ClonedF = cloneFunctionDecl(*M, *F);
451        makeStub(*ClonedF, *StubPtr);
452        ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
453        ClonedF->addFnAttr(Attribute::AlwaysInline);
454        return ClonedF;
455      }
456
457      if (auto *A = dyn_cast<GlobalAlias>(V)) {
458        auto *Ty = A->getValueType();
459        if (Ty->isFunctionTy())
460          return Function::Create(cast<FunctionType>(Ty),
461                                  GlobalValue::ExternalLinkage, A->getName(),
462                                  M.get());
463
464        return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
465                                  nullptr, A->getName(), nullptr,
466                                  GlobalValue::NotThreadLocal,
467                                  A->getType()->getAddressSpace());
468      }
469
470      return nullptr;
471    });
472
473    // Create decls in the new module.
474    for (auto *F : Part)
475      cloneFunctionDecl(*M, *F, &VMap);
476
477    // Move the function bodies.
478    for (auto *F : Part)
479      moveFunctionBody(*F, VMap, &Materializer);
480
481    // Create memory manager and symbol resolver.
482    auto Resolver = createLambdaResolver(
483        [this, &LD, LMH](const std::string &Name) {
484          if (auto Symbol = LD.findSymbolInternally(LMH, Name))
485            return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
486                                           Symbol.getFlags());
487          return LD.getDylibResources().ExternalSymbolResolver(Name);
488        },
489        [this, &LD, LMH](const std::string &Name) {
490          if (auto Symbol = LD.findSymbolInternally(LMH, Name))
491            return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
492                                           Symbol.getFlags());
493          return RuntimeDyld::SymbolInfo(nullptr);
494        });
495
496    return LD.getDylibResources().ModuleAdder(BaseLayer, std::move(M),
497					      std::move(Resolver));
498  }
499
500  BaseLayerT &BaseLayer;
501  PartitioningFtor Partition;
502  CompileCallbackMgrT &CompileCallbackMgr;
503  IndirectStubsManagerBuilderT CreateIndirectStubsManager;
504
505  LogicalDylibList LogicalDylibs;
506  bool CloneStubsIntoPartitions;
507};
508
509} // End namespace orc.
510} // End namespace llvm.
511
512#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
513