blob: ca1ce40cdaef1fd1598b58bde15092ce09cc9543 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9// JIT layer for breaking up modules and inserting callbacks to allow
10// individual functions to be compiled on demand.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
15#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16
17#include "llvm/ADT/APInt.h"
Andrew Scull0372a572018-11-16 15:47:06 +000018#include "llvm/ADT/Optional.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010019#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/ExecutionEngine/JITSymbol.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010023#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
24#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010025#include "llvm/ExecutionEngine/Orc/Layer.h"
Andrew Scull0372a572018-11-16 15:47:06 +000026#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010027#include "llvm/ExecutionEngine/Orc/Legacy.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010028#include "llvm/ExecutionEngine/Orc/OrcError.h"
29#include "llvm/ExecutionEngine/RuntimeDyld.h"
30#include "llvm/IR/Attributes.h"
31#include "llvm/IR/Constant.h"
32#include "llvm/IR/Constants.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/Function.h"
35#include "llvm/IR/GlobalAlias.h"
36#include "llvm/IR/GlobalValue.h"
37#include "llvm/IR/GlobalVariable.h"
38#include "llvm/IR/Instruction.h"
39#include "llvm/IR/Mangler.h"
40#include "llvm/IR/Module.h"
41#include "llvm/IR/Type.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/raw_ostream.h"
44#include "llvm/Transforms/Utils/ValueMapper.h"
45#include <algorithm>
46#include <cassert>
47#include <functional>
48#include <iterator>
49#include <list>
50#include <memory>
51#include <set>
52#include <string>
53#include <utility>
54#include <vector>
55
56namespace llvm {
57
58class Value;
59
60namespace orc {
61
Andrew Scullcdfcccc2018-10-05 20:58:37 +010062class ExtractingIRMaterializationUnit;
63
Andrew Walbran16937d02019-10-22 13:54:20 +010064class CompileOnDemandLayer : public IRLayer {
Andrew Scull0372a572018-11-16 15:47:06 +000065 friend class PartitioningIRMaterializationUnit;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010066
67public:
68 /// Builder for IndirectStubsManagers.
69 using IndirectStubsManagerBuilder =
70 std::function<std::unique_ptr<IndirectStubsManager>()>;
71
Andrew Scull0372a572018-11-16 15:47:06 +000072 using GlobalValueSet = std::set<const GlobalValue *>;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010073
Andrew Scull0372a572018-11-16 15:47:06 +000074 /// Partitioning function.
75 using PartitionFunction =
76 std::function<Optional<GlobalValueSet>(GlobalValueSet Requested)>;
77
78 /// Off-the-shelf partitioning which compiles all requested symbols (usually
79 /// a single function at a time).
80 static Optional<GlobalValueSet> compileRequested(GlobalValueSet Requested);
81
82 /// Off-the-shelf partitioning which compiles whole modules whenever any
83 /// symbol in them is requested.
84 static Optional<GlobalValueSet> compileWholeModule(GlobalValueSet Requested);
85
Andrew Walbran16937d02019-10-22 13:54:20 +010086 /// Construct a CompileOnDemandLayer.
87 CompileOnDemandLayer(ExecutionSession &ES, IRLayer &BaseLayer,
Andrew Scull0372a572018-11-16 15:47:06 +000088 LazyCallThroughManager &LCTMgr,
89 IndirectStubsManagerBuilder BuildIndirectStubsManager);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010090
Andrew Scull0372a572018-11-16 15:47:06 +000091 /// Sets the partition function.
92 void setPartitionFunction(PartitionFunction Partition);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010093
Andrew Scull0372a572018-11-16 15:47:06 +000094 /// Emits the given module. This should not be called by clients: it will be
95 /// called by the JIT when a definition added via the add method is requested.
Andrew Walbran16937d02019-10-22 13:54:20 +010096 void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010097
98private:
Andrew Scull0372a572018-11-16 15:47:06 +000099 struct PerDylibResources {
100 public:
101 PerDylibResources(JITDylib &ImplD,
102 std::unique_ptr<IndirectStubsManager> ISMgr)
103 : ImplD(ImplD), ISMgr(std::move(ISMgr)) {}
104 JITDylib &getImplDylib() { return ImplD; }
105 IndirectStubsManager &getISManager() { return *ISMgr; }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100106
Andrew Scull0372a572018-11-16 15:47:06 +0000107 private:
108 JITDylib &ImplD;
109 std::unique_ptr<IndirectStubsManager> ISMgr;
110 };
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100111
Andrew Scull0372a572018-11-16 15:47:06 +0000112 using PerDylibResourcesMap = std::map<const JITDylib *, PerDylibResources>;
113
114 PerDylibResources &getPerDylibResources(JITDylib &TargetD);
115
116 void cleanUpModule(Module &M);
117
118 void expandPartition(GlobalValueSet &Partition);
119
120 void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM,
121 IRMaterializationUnit::SymbolNameToDefinitionMap Defs);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100122
123 mutable std::mutex CODLayerMutex;
124
125 IRLayer &BaseLayer;
Andrew Scull0372a572018-11-16 15:47:06 +0000126 LazyCallThroughManager &LCTMgr;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100127 IndirectStubsManagerBuilder BuildIndirectStubsManager;
Andrew Scull0372a572018-11-16 15:47:06 +0000128 PerDylibResourcesMap DylibResources;
129 PartitionFunction Partition = compileRequested;
130 SymbolLinkagePromoter PromoteSymbols;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100131};
132
133/// Compile-on-demand layer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100134///
135/// When a module is added to this layer a stub is created for each of its
136/// function definitions. The stubs and other global values are immediately
137/// added to the layer below. When a stub is called it triggers the extraction
138/// of the function body from the original module. The extracted body is then
139/// compiled and executed.
140template <typename BaseLayerT,
141 typename CompileCallbackMgrT = JITCompileCallbackManager,
142 typename IndirectStubsMgrT = IndirectStubsManager>
Andrew Walbran16937d02019-10-22 13:54:20 +0100143class LegacyCompileOnDemandLayer {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100144private:
145 template <typename MaterializerFtor>
146 class LambdaMaterializer final : public ValueMaterializer {
147 public:
148 LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
149
150 Value *materialize(Value *V) final { return M(V); }
151
152 private:
153 MaterializerFtor M;
154 };
155
156 template <typename MaterializerFtor>
157 LambdaMaterializer<MaterializerFtor>
158 createLambdaMaterializer(MaterializerFtor M) {
159 return LambdaMaterializer<MaterializerFtor>(std::move(M));
160 }
161
162 // Provide type-erasure for the Modules and MemoryManagers.
163 template <typename ResourceT>
164 class ResourceOwner {
165 public:
166 ResourceOwner() = default;
167 ResourceOwner(const ResourceOwner &) = delete;
168 ResourceOwner &operator=(const ResourceOwner &) = delete;
169 virtual ~ResourceOwner() = default;
170
171 virtual ResourceT& getResource() const = 0;
172 };
173
174 template <typename ResourceT, typename ResourcePtrT>
175 class ResourceOwnerImpl : public ResourceOwner<ResourceT> {
176 public:
177 ResourceOwnerImpl(ResourcePtrT ResourcePtr)
178 : ResourcePtr(std::move(ResourcePtr)) {}
179
180 ResourceT& getResource() const override { return *ResourcePtr; }
181
182 private:
183 ResourcePtrT ResourcePtr;
184 };
185
186 template <typename ResourceT, typename ResourcePtrT>
187 std::unique_ptr<ResourceOwner<ResourceT>>
188 wrapOwnership(ResourcePtrT ResourcePtr) {
189 using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>;
190 return llvm::make_unique<RO>(std::move(ResourcePtr));
191 }
192
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100193 struct LogicalDylib {
194 struct SourceModuleEntry {
195 std::unique_ptr<Module> SourceMod;
196 std::set<Function*> StubsToClone;
197 };
198
199 using SourceModulesList = std::vector<SourceModuleEntry>;
200 using SourceModuleHandle = typename SourceModulesList::size_type;
201
202 LogicalDylib() = default;
203
204 LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver,
205 std::unique_ptr<IndirectStubsMgrT> StubsMgr)
206 : K(std::move(K)), BackingResolver(std::move(BackingResolver)),
207 StubsMgr(std::move(StubsMgr)) {}
208
209 SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) {
210 SourceModuleHandle H = SourceModules.size();
211 SourceModules.push_back(SourceModuleEntry());
212 SourceModules.back().SourceMod = std::move(M);
213 return H;
214 }
215
216 Module& getSourceModule(SourceModuleHandle H) {
217 return *SourceModules[H].SourceMod;
218 }
219
220 std::set<Function*>& getStubsToClone(SourceModuleHandle H) {
221 return SourceModules[H].StubsToClone;
222 }
223
224 JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name,
225 bool ExportedSymbolsOnly) {
226 if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly))
227 return Sym;
228 for (auto BLK : BaseLayerVModuleKeys)
229 if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly))
230 return Sym;
231 else if (auto Err = Sym.takeError())
232 return std::move(Err);
233 return nullptr;
234 }
235
236 Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
237 for (auto &BLK : BaseLayerVModuleKeys)
238 if (auto Err = BaseLayer.removeModule(BLK))
239 return Err;
240 return Error::success();
241 }
242
243 VModuleKey K;
244 std::shared_ptr<SymbolResolver> BackingResolver;
245 std::unique_ptr<IndirectStubsMgrT> StubsMgr;
Andrew Scull0372a572018-11-16 15:47:06 +0000246 SymbolLinkagePromoter PromoteSymbols;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100247 SourceModulesList SourceModules;
248 std::vector<VModuleKey> BaseLayerVModuleKeys;
249 };
250
251public:
252
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100253 /// Module partitioning functor.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100254 using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
255
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100256 /// Builder for IndirectStubsManagers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100257 using IndirectStubsManagerBuilderT =
258 std::function<std::unique_ptr<IndirectStubsMgrT>()>;
259
260 using SymbolResolverGetter =
261 std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>;
262
263 using SymbolResolverSetter =
264 std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
265
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100266 /// Construct a compile-on-demand layer instance.
Andrew Walbran16937d02019-10-22 13:54:20 +0100267 LegacyCompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer,
268 SymbolResolverGetter GetSymbolResolver,
269 SymbolResolverSetter SetSymbolResolver,
270 PartitioningFtor Partition,
271 CompileCallbackMgrT &CallbackMgr,
272 IndirectStubsManagerBuilderT CreateIndirectStubsManager,
273 bool CloneStubsIntoPartitions = true)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100274 : ES(ES), BaseLayer(BaseLayer),
275 GetSymbolResolver(std::move(GetSymbolResolver)),
276 SetSymbolResolver(std::move(SetSymbolResolver)),
277 Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
278 CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
279 CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
280
Andrew Walbran16937d02019-10-22 13:54:20 +0100281 ~LegacyCompileOnDemandLayer() {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100282 // FIXME: Report error on log.
283 while (!LogicalDylibs.empty())
284 consumeError(removeModule(LogicalDylibs.begin()->first));
285 }
286
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100287 /// Add a module to the compile-on-demand layer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100288 Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
289
290 assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
291 auto I = LogicalDylibs.insert(
292 LogicalDylibs.end(),
293 std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K),
294 CreateIndirectStubsManager())));
295
296 return addLogicalModule(I->second, std::move(M));
297 }
298
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100299 /// Add extra modules to an existing logical module.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100300 Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
301 return addLogicalModule(LogicalDylibs[K], std::move(M));
302 }
303
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100304 /// Remove the module represented by the given key.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100305 ///
306 /// This will remove all modules in the layers below that were derived from
307 /// the module represented by K.
308 Error removeModule(VModuleKey K) {
309 auto I = LogicalDylibs.find(K);
310 assert(I != LogicalDylibs.end() && "VModuleKey K not valid here");
311 auto Err = I->second.removeModulesFromBaseLayer(BaseLayer);
312 LogicalDylibs.erase(I);
313 return Err;
314 }
315
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100316 /// Search for the given named symbol.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100317 /// @param Name The name of the symbol to search for.
318 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
319 /// @return A handle for the given named symbol, if it exists.
320 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
321 for (auto &KV : LogicalDylibs) {
322 if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly))
323 return Sym;
324 if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly))
325 return Sym;
326 else if (auto Err = Sym.takeError())
327 return std::move(Err);
328 }
329 return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
330 }
331
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100332 /// Get the address of a symbol provided by this layer, or some layer
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100333 /// below this one.
334 JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
335 bool ExportedSymbolsOnly) {
336 assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here");
337 return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
338 }
339
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100340 /// Update the stub for the given function to point at FnBodyAddr.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100341 /// This can be used to support re-optimization.
342 /// @return true if the function exists and the stub is updated, false
343 /// otherwise.
344 //
345 // FIXME: We should track and free associated resources (unused compile
346 // callbacks, uncompiled IR, and no-longer-needed/reachable function
347 // implementations).
348 Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) {
349 //Find out which logical dylib contains our symbol
350 auto LDI = LogicalDylibs.begin();
351 for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) {
352 if (auto LMResources =
353 LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) {
354 Module &SrcM = LMResources->SourceModule->getResource();
355 std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout());
356 if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName,
357 FnBodyAddr))
358 return Err;
359 return Error::success();
360 }
361 }
362 return make_error<JITSymbolNotFound>(FuncName);
363 }
364
365private:
366 Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
367
Andrew Scull0372a572018-11-16 15:47:06 +0000368 // Rename anonymous globals and promote linkage to ensure that everything
369 // will resolve properly after we partition SrcM.
370 LD.PromoteSymbols(*SrcMPtr);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100371
372 // Create a logical module handle for SrcM within the logical dylib.
373 Module &SrcM = *SrcMPtr;
374 auto LMId = LD.addSourceModule(std::move(SrcMPtr));
375
376 // Create stub functions.
377 const DataLayout &DL = SrcM.getDataLayout();
378 {
379 typename IndirectStubsMgrT::StubInitsMap StubInits;
380 for (auto &F : SrcM) {
381 // Skip declarations.
382 if (F.isDeclaration())
383 continue;
384
385 // Skip weak functions for which we already have definitions.
386 auto MangledName = mangle(F.getName(), DL);
387 if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
388 if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
389 continue;
390 else if (auto Err = Sym.takeError())
391 return std::move(Err);
392 }
393
394 // Record all functions defined by this module.
395 if (CloneStubsIntoPartitions)
396 LD.getStubsToClone(LMId).insert(&F);
397
398 // Create a callback, associate it with the stub for the function,
399 // and set the compile action to compile the partition containing the
400 // function.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100401 auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress {
402 if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
403 return *FnImplAddrOrErr;
404 else {
405 // FIXME: Report error, return to 'abort' or something similar.
406 consumeError(FnImplAddrOrErr.takeError());
407 return 0;
408 }
409 };
410 if (auto CCAddr =
411 CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100412 StubInits[MangledName] =
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100413 std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
414 else
415 return CCAddr.takeError();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100416 }
417
418 if (auto Err = LD.StubsMgr->createStubs(StubInits))
419 return Err;
420 }
421
422 // If this module doesn't contain any globals, aliases, or module flags then
423 // we can bail out early and avoid the overhead of creating and managing an
424 // empty globals module.
425 if (SrcM.global_empty() && SrcM.alias_empty() &&
426 !SrcM.getModuleFlagsMetadata())
427 return Error::success();
428
429 // Create the GlobalValues module.
430 auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
431 SrcM.getContext());
432 GVsM->setDataLayout(DL);
433
434 ValueToValueMapTy VMap;
435
436 // Clone global variable decls.
437 for (auto &GV : SrcM.globals())
438 if (!GV.isDeclaration() && !VMap.count(&GV))
439 cloneGlobalVariableDecl(*GVsM, GV, &VMap);
440
441 // And the aliases.
442 for (auto &A : SrcM.aliases())
443 if (!VMap.count(&A))
444 cloneGlobalAliasDecl(*GVsM, A, VMap);
445
446 // Clone the module flags.
447 cloneModuleFlagsMetadata(*GVsM, SrcM, VMap);
448
449 // Now we need to clone the GV and alias initializers.
450
451 // Initializers may refer to functions declared (but not defined) in this
452 // module. Build a materializer to clone decls on demand.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100453 auto Materializer = createLambdaMaterializer(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100454 [&LD, &GVsM](Value *V) -> Value* {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100455 if (auto *F = dyn_cast<Function>(V)) {
456 // Decls in the original module just get cloned.
457 if (F->isDeclaration())
458 return cloneFunctionDecl(*GVsM, *F);
459
460 // Definitions in the original module (which we have emitted stubs
461 // for at this point) get turned into a constant alias to the stub
462 // instead.
463 const DataLayout &DL = GVsM->getDataLayout();
464 std::string FName = mangle(F->getName(), DL);
465 unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100466 JITTargetAddress StubAddr =
467 LD.StubsMgr->findStub(FName, false).getAddress();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100468
469 ConstantInt *StubAddrCI =
470 ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
471 Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
472 StubAddrCI, F->getType());
473 return GlobalAlias::create(F->getFunctionType(),
474 F->getType()->getAddressSpace(),
475 F->getLinkage(), F->getName(),
476 Init, GVsM.get());
477 }
478 // else....
479 return nullptr;
480 });
481
482 // Clone the global variable initializers.
483 for (auto &GV : SrcM.globals())
484 if (!GV.isDeclaration())
485 moveGlobalVariableInitializer(GV, VMap, &Materializer);
486
487 // Clone the global alias initializers.
488 for (auto &A : SrcM.aliases()) {
489 auto *NewA = cast<GlobalAlias>(VMap[&A]);
490 assert(NewA && "Alias not cloned?");
491 Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
492 &Materializer);
493 NewA->setAliasee(cast<Constant>(Init));
494 }
495
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100496 // Build a resolver for the globals module and add it to the base layer.
497 auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
498 if (auto Sym = LD.StubsMgr->findStub(Name, false))
499 return Sym;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100500
501 if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
502 return Sym;
503 else if (auto Err = Sym.takeError())
504 return std::move(Err);
505
506 return nullptr;
507 };
508
509 auto GVsResolver = createSymbolResolver(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100510 [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
Andrew Scull0372a572018-11-16 15:47:06 +0000511 auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100512
Andrew Scull0372a572018-11-16 15:47:06 +0000513 if (!RS) {
514 logAllUnhandledErrors(
515 RS.takeError(), errs(),
516 "CODLayer/GVsResolver responsibility set lookup failed: ");
517 return SymbolNameSet();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100518 }
519
Andrew Scull0372a572018-11-16 15:47:06 +0000520 if (RS->size() == Symbols.size())
521 return *RS;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100522
523 SymbolNameSet NotFoundViaLegacyLookup;
524 for (auto &S : Symbols)
Andrew Scull0372a572018-11-16 15:47:06 +0000525 if (!RS->count(S))
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100526 NotFoundViaLegacyLookup.insert(S);
Andrew Scull0372a572018-11-16 15:47:06 +0000527 auto RS2 =
528 LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100529
Andrew Scull0372a572018-11-16 15:47:06 +0000530 for (auto &S : RS2)
531 (*RS).insert(S);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100532
Andrew Scull0372a572018-11-16 15:47:06 +0000533 return *RS;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100534 },
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100535 [this, &LD,
536 LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
537 SymbolNameSet Symbols) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100538 auto NotFoundViaLegacyLookup =
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100539 lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100540 return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
541 });
542
543 SetSymbolResolver(LD.K, std::move(GVsResolver));
544
545 if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM)))
546 return Err;
547
548 LD.BaseLayerVModuleKeys.push_back(LD.K);
549
550 return Error::success();
551 }
552
553 static std::string mangle(StringRef Name, const DataLayout &DL) {
554 std::string MangledName;
555 {
556 raw_string_ostream MangledNameStream(MangledName);
557 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
558 }
559 return MangledName;
560 }
561
562 Expected<JITTargetAddress>
563 extractAndCompile(LogicalDylib &LD,
564 typename LogicalDylib::SourceModuleHandle LMId,
565 Function &F) {
566 Module &SrcM = LD.getSourceModule(LMId);
567
568 // If F is a declaration we must already have compiled it.
569 if (F.isDeclaration())
570 return 0;
571
572 // Grab the name of the function being called here.
573 std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
574
575 JITTargetAddress CalledAddr = 0;
576 auto Part = Partition(F);
577 if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) {
578 auto &PartKey = *PartKeyOrErr;
579 for (auto *SubF : Part) {
580 std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
581 if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) {
582 if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
583 JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
584
585 // If this is the function we're calling record the address so we can
586 // return it from this function.
587 if (SubF == &F)
588 CalledAddr = FnBodyAddr;
589
590 // Update the function body pointer for the stub.
591 if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
592 return 0;
593
594 } else
595 return FnBodyAddrOrErr.takeError();
596 } else if (auto Err = FnBodySym.takeError())
597 return std::move(Err);
598 else
599 llvm_unreachable("Function not emitted for partition");
600 }
601
602 LD.BaseLayerVModuleKeys.push_back(PartKey);
603 } else
604 return PartKeyOrErr.takeError();
605
606 return CalledAddr;
607 }
608
609 template <typename PartitionT>
610 Expected<VModuleKey>
611 emitPartition(LogicalDylib &LD,
612 typename LogicalDylib::SourceModuleHandle LMId,
613 const PartitionT &Part) {
614 Module &SrcM = LD.getSourceModule(LMId);
615
616 // Create the module.
617 std::string NewName = SrcM.getName();
618 for (auto *F : Part) {
619 NewName += ".";
620 NewName += F->getName();
621 }
622
623 auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
624 M->setDataLayout(SrcM.getDataLayout());
625 ValueToValueMapTy VMap;
626
627 auto Materializer = createLambdaMaterializer([&LD, &LMId,
628 &M](Value *V) -> Value * {
629 if (auto *GV = dyn_cast<GlobalVariable>(V))
630 return cloneGlobalVariableDecl(*M, *GV);
631
632 if (auto *F = dyn_cast<Function>(V)) {
633 // Check whether we want to clone an available_externally definition.
634 if (!LD.getStubsToClone(LMId).count(F))
635 return cloneFunctionDecl(*M, *F);
636
637 // Ok - we want an inlinable stub. For that to work we need a decl
638 // for the stub pointer.
639 auto *StubPtr = createImplPointer(*F->getType(), *M,
640 F->getName() + "$stub_ptr", nullptr);
641 auto *ClonedF = cloneFunctionDecl(*M, *F);
642 makeStub(*ClonedF, *StubPtr);
643 ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
644 ClonedF->addFnAttr(Attribute::AlwaysInline);
645 return ClonedF;
646 }
647
648 if (auto *A = dyn_cast<GlobalAlias>(V)) {
649 auto *Ty = A->getValueType();
650 if (Ty->isFunctionTy())
651 return Function::Create(cast<FunctionType>(Ty),
652 GlobalValue::ExternalLinkage, A->getName(),
653 M.get());
654
655 return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
656 nullptr, A->getName(), nullptr,
657 GlobalValue::NotThreadLocal,
658 A->getType()->getAddressSpace());
659 }
660
661 return nullptr;
662 });
663
664 // Create decls in the new module.
665 for (auto *F : Part)
666 cloneFunctionDecl(*M, *F, &VMap);
667
668 // Move the function bodies.
669 for (auto *F : Part)
670 moveFunctionBody(*F, VMap, &Materializer);
671
672 auto K = ES.allocateVModule();
673
674 auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
675 return LD.findSymbol(BaseLayer, Name, false);
676 };
677
678 // Create memory manager and symbol resolver.
679 auto Resolver = createSymbolResolver(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100680 [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
Andrew Scull0372a572018-11-16 15:47:06 +0000681 auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
682 if (!RS) {
683 logAllUnhandledErrors(
684 RS.takeError(), errs(),
685 "CODLayer/SubResolver responsibility set lookup failed: ");
686 return SymbolNameSet();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100687 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100688
Andrew Scull0372a572018-11-16 15:47:06 +0000689 if (RS->size() == Symbols.size())
690 return *RS;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100691
692 SymbolNameSet NotFoundViaLegacyLookup;
693 for (auto &S : Symbols)
Andrew Scull0372a572018-11-16 15:47:06 +0000694 if (!RS->count(S))
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100695 NotFoundViaLegacyLookup.insert(S);
696
Andrew Scull0372a572018-11-16 15:47:06 +0000697 auto RS2 =
698 LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100699
Andrew Scull0372a572018-11-16 15:47:06 +0000700 for (auto &S : RS2)
701 (*RS).insert(S);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100702
Andrew Scull0372a572018-11-16 15:47:06 +0000703 return *RS;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100704 },
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100705 [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
706 SymbolNameSet Symbols) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100707 auto NotFoundViaLegacyLookup =
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100708 lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100709 return LD.BackingResolver->lookup(Q,
710 std::move(NotFoundViaLegacyLookup));
711 });
712 SetSymbolResolver(K, std::move(Resolver));
713
714 if (auto Err = BaseLayer.addModule(std::move(K), std::move(M)))
715 return std::move(Err);
716
717 return K;
718 }
719
720 ExecutionSession &ES;
721 BaseLayerT &BaseLayer;
722 SymbolResolverGetter GetSymbolResolver;
723 SymbolResolverSetter SetSymbolResolver;
724 PartitioningFtor Partition;
725 CompileCallbackMgrT &CompileCallbackMgr;
726 IndirectStubsManagerBuilderT CreateIndirectStubsManager;
727
728 std::map<VModuleKey, LogicalDylib> LogicalDylibs;
729 bool CloneStubsIntoPartitions;
730};
731
732} // end namespace orc
733
734} // end namespace llvm
735
736#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H