blob: e8d24f99faeee5ccbf58b2ef587be9d8d7398bba [file] [log] [blame]
Lang Hames68c9b8d2018-06-18 18:01:43 +00001//===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===//
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#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
Lang Hames7bd89702018-07-05 19:01:27 +000011#include "llvm/Bitcode/BitcodeReader.h"
12#include "llvm/Bitcode/BitcodeWriter.h"
Lang Hames68c9b8d2018-06-18 18:01:43 +000013#include "llvm/IR/Mangler.h"
14#include "llvm/IR/Module.h"
15#include "llvm/Support/raw_ostream.h"
Lang Hames7bd89702018-07-05 19:01:27 +000016#include "llvm/Transforms/Utils/Cloning.h"
Lang Hames68c9b8d2018-06-18 18:01:43 +000017
18using namespace llvm;
19using namespace llvm::orc;
20
21namespace {
22
23template <typename MaterializerFtor>
24class LambdaValueMaterializer final : public ValueMaterializer {
25public:
26 LambdaValueMaterializer(MaterializerFtor M) : M(std::move(M)) {}
27
28 Value *materialize(Value *V) final { return M(V); }
29
30private:
31 MaterializerFtor M;
32};
33
34template <typename MaterializerFtor>
35LambdaValueMaterializer<MaterializerFtor>
36createLambdaValueMaterializer(MaterializerFtor M) {
37 return LambdaValueMaterializer<MaterializerFtor>(std::move(M));
38}
39} // namespace
40
Lang Hames6a941342018-06-26 21:35:48 +000041static void extractAliases(MaterializationResponsibility &R, Module &M,
42 MangleAndInterner &Mangle) {
43 SymbolAliasMap Aliases;
44
45 std::vector<GlobalAlias *> ModAliases;
46 for (auto &A : M.aliases())
47 ModAliases.push_back(&A);
48
49 for (auto *A : ModAliases) {
50 Constant *Aliasee = A->getAliasee();
51 assert(A->hasName() && "Anonymous alias?");
52 assert(Aliasee->hasName() && "Anonymous aliasee");
53 std::string AliasName = A->getName();
54
55 Aliases[Mangle(AliasName)] = SymbolAliasMapEntry(
56 {Mangle(Aliasee->getName()), JITSymbolFlags::fromGlobalValue(*A)});
57
58 if (isa<Function>(Aliasee)) {
59 auto *F = cloneFunctionDecl(M, *cast<Function>(Aliasee));
60 A->replaceAllUsesWith(F);
61 A->eraseFromParent();
62 F->setName(AliasName);
63 } else if (isa<GlobalValue>(Aliasee)) {
64 auto *G = cloneGlobalVariableDecl(M, *cast<GlobalVariable>(Aliasee));
65 A->replaceAllUsesWith(G);
66 A->eraseFromParent();
67 G->setName(AliasName);
68 }
69 }
70
71 R.delegate(symbolAliases(std::move(Aliases)));
72}
73
Lang Hames7bd89702018-07-05 19:01:27 +000074static std::unique_ptr<Module>
75extractAndClone(Module &M, LLVMContext &NewContext, StringRef Suffix,
76 function_ref<bool(const GlobalValue *)> ShouldCloneDefinition) {
77 SmallVector<char, 1> ClonedModuleBuffer;
Lang Hames68c9b8d2018-06-18 18:01:43 +000078
Lang Hames7bd89702018-07-05 19:01:27 +000079 {
80 std::set<GlobalValue *> ClonedDefsInSrc;
81 ValueToValueMapTy VMap;
82 auto Tmp = CloneModule(M, VMap, [&](const GlobalValue *GV) {
83 if (ShouldCloneDefinition(GV)) {
84 ClonedDefsInSrc.insert(const_cast<GlobalValue *>(GV));
85 return true;
86 }
87 return false;
88 });
Lang Hames68c9b8d2018-06-18 18:01:43 +000089
Lang Hames7bd89702018-07-05 19:01:27 +000090 for (auto *GV : ClonedDefsInSrc) {
91 // Delete the definition and bump the linkage in the source module.
92 if (isa<Function>(GV)) {
93 auto &F = *cast<Function>(GV);
94 F.deleteBody();
95 F.setPersonalityFn(nullptr);
96 } else if (isa<GlobalVariable>(GV)) {
97 cast<GlobalVariable>(GV)->setInitializer(nullptr);
98 } else
99 llvm_unreachable("Unsupported global type");
Lang Hames68c9b8d2018-06-18 18:01:43 +0000100
Lang Hames7bd89702018-07-05 19:01:27 +0000101 GV->setLinkage(GlobalValue::ExternalLinkage);
102 }
Lang Hames68c9b8d2018-06-18 18:01:43 +0000103
Lang Hames7bd89702018-07-05 19:01:27 +0000104 BitcodeWriter BCWriter(ClonedModuleBuffer);
Lang Hames68c9b8d2018-06-18 18:01:43 +0000105
Lang Hames7bd89702018-07-05 19:01:27 +0000106 BCWriter.writeModule(*Tmp);
107 BCWriter.writeSymtab();
108 BCWriter.writeStrtab();
Lang Hames68c9b8d2018-06-18 18:01:43 +0000109 }
110
Lang Hames7bd89702018-07-05 19:01:27 +0000111 MemoryBufferRef ClonedModuleBufferRef(
112 StringRef(ClonedModuleBuffer.data(), ClonedModuleBuffer.size()),
113 "cloned module buffer");
114
115 auto ClonedModule =
116 cantFail(parseBitcodeFile(ClonedModuleBufferRef, NewContext));
117 ClonedModule->setModuleIdentifier((M.getName() + Suffix).str());
118 return ClonedModule;
119}
120
121static std::unique_ptr<Module> extractGlobals(Module &M,
122 LLVMContext &NewContext) {
123 return extractAndClone(M, NewContext, ".globals", [](const GlobalValue *GV) {
124 return isa<GlobalVariable>(GV);
125 });
Lang Hames68c9b8d2018-06-18 18:01:43 +0000126}
127
128namespace llvm {
129namespace orc {
130
131class ExtractingIRMaterializationUnit : public IRMaterializationUnit {
132public:
133 ExtractingIRMaterializationUnit(
134 ExecutionSession &ES, CompileOnDemandLayer2 &Parent,
135 std::unique_ptr<Module> M,
136 std::shared_ptr<SymbolResolver> BackingResolver)
137 : IRMaterializationUnit(ES, std::move(M)), Parent(Parent),
138 BackingResolver(std::move(BackingResolver)) {}
139
140 ExtractingIRMaterializationUnit(
141 std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
142 SymbolNameToDefinitionMap SymbolToDefinition,
143 CompileOnDemandLayer2 &Parent,
144 std::shared_ptr<SymbolResolver> BackingResolver)
145 : IRMaterializationUnit(std::move(M), std::move(SymbolFlags),
146 std::move(SymbolToDefinition)),
147 Parent(Parent), BackingResolver(std::move(BackingResolver)) {}
148
149private:
150 void materialize(MaterializationResponsibility R) override {
151 // FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the
152 // extracted module key, extracted module, and source module key
153 // together. This could be used, for example, to provide a specific
154 // memory manager instance to the linking layer.
155
156 // FIXME: The derived constructor should *only* look for the names of
157 // original function definitions in the target VSO. All other
158 // symbols should be looked up in the backing resolver.
159
Lang Hames68c9b8d2018-06-18 18:01:43 +0000160 auto RequestedSymbols = R.getRequestedSymbols();
161
Lang Hames7bd89702018-07-05 19:01:27 +0000162 // Extract the requested functions into a new module.
163 std::unique_ptr<Module> ExtractedFunctionsModule;
164 if (!RequestedSymbols.empty()) {
165 std::string Suffix;
166 std::set<const GlobalValue *> FunctionsToClone;
167 for (auto &Name : RequestedSymbols) {
168 auto I = SymbolToDefinition.find(Name);
169 assert(I != SymbolToDefinition.end() && I->second != nullptr &&
170 "Should have a non-null definition");
171 FunctionsToClone.insert(I->second);
172 Suffix += ".";
173 Suffix += *Name;
174 }
175
176 std::lock_guard<std::mutex> Lock(SourceModuleMutex);
177 ExtractedFunctionsModule =
178 extractAndClone(*M, Parent.GetAvailableContext(), Suffix,
179 [&](const GlobalValue *GV) -> bool {
180 return FunctionsToClone.count(GV);
181 });
182 }
Lang Hames68c9b8d2018-06-18 18:01:43 +0000183
184 // Build a new ExtractingIRMaterializationUnit to delegate the unrequested
185 // symbols to.
186 SymbolFlagsMap DelegatedSymbolFlags;
187 IRMaterializationUnit::SymbolNameToDefinitionMap
188 DelegatedSymbolToDefinition;
189 for (auto &KV : SymbolToDefinition) {
190 if (RequestedSymbols.count(KV.first))
191 continue;
192 DelegatedSymbolFlags[KV.first] =
193 JITSymbolFlags::fromGlobalValue(*KV.second);
194 DelegatedSymbolToDefinition[KV.first] = KV.second;
195 }
196
197 if (!DelegatedSymbolFlags.empty()) {
198 assert(DelegatedSymbolFlags.size() ==
199 DelegatedSymbolToDefinition.size() &&
200 "SymbolFlags and SymbolToDefinition should have the same number "
201 "of entries");
202 R.delegate(llvm::make_unique<ExtractingIRMaterializationUnit>(
203 std::move(M), std::move(DelegatedSymbolFlags),
204 std::move(DelegatedSymbolToDefinition), Parent, BackingResolver));
205 }
206
Lang Hames7bd89702018-07-05 19:01:27 +0000207 if (ExtractedFunctionsModule)
208 Parent.emitExtractedFunctionsModule(
209 std::move(R), std::move(ExtractedFunctionsModule), BackingResolver);
Lang Hames68c9b8d2018-06-18 18:01:43 +0000210 }
211
212 void discard(const VSO &V, SymbolStringPtr Name) override {
213 // All original symbols were materialized by the CODLayer and should be
214 // final. The function bodies provided by M should never be overridden.
215 llvm_unreachable("Discard should never be called on an "
216 "ExtractingIRMaterializationUnit");
217 }
218
Lang Hames7bd89702018-07-05 19:01:27 +0000219 mutable std::mutex SourceModuleMutex;
Lang Hames68c9b8d2018-06-18 18:01:43 +0000220 CompileOnDemandLayer2 &Parent;
221 std::shared_ptr<SymbolResolver> BackingResolver;
222};
223
224CompileOnDemandLayer2::CompileOnDemandLayer2(
225 ExecutionSession &ES, IRLayer &BaseLayer, JITCompileCallbackManager &CCMgr,
226 IndirectStubsManagerBuilder BuildIndirectStubsManager,
227 GetSymbolResolverFunction GetSymbolResolver,
228 SetSymbolResolverFunction SetSymbolResolver,
229 GetAvailableContextFunction GetAvailableContext)
230 : IRLayer(ES), BaseLayer(BaseLayer), CCMgr(CCMgr),
231 BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)),
232 GetSymbolResolver(std::move(GetSymbolResolver)),
233 SetSymbolResolver(std::move(SetSymbolResolver)),
234 GetAvailableContext(std::move(GetAvailableContext)) {}
235
236Error CompileOnDemandLayer2::add(VSO &V, VModuleKey K,
237 std::unique_ptr<Module> M) {
Lang Hames68c9b8d2018-06-18 18:01:43 +0000238 return IRLayer::add(V, K, std::move(M));
239}
240
241void CompileOnDemandLayer2::emit(MaterializationResponsibility R, VModuleKey K,
242 std::unique_ptr<Module> M) {
243 auto &ES = getExecutionSession();
244 assert(M && "M should not be null");
245
246 for (auto &GV : M->global_values())
247 if (GV.hasWeakLinkage())
248 GV.setLinkage(GlobalValue::ExternalLinkage);
249
Lang Hames68c9b8d2018-06-18 18:01:43 +0000250 MangleAndInterner Mangle(ES, M->getDataLayout());
251
Lang Hames6a941342018-06-26 21:35:48 +0000252 extractAliases(R, *M, Mangle);
253
Lang Hames7bd89702018-07-05 19:01:27 +0000254 auto GlobalsModule = extractGlobals(*M, GetAvailableContext());
Lang Hames6a941342018-06-26 21:35:48 +0000255
Lang Hames68c9b8d2018-06-18 18:01:43 +0000256 // Delete the bodies of any available externally functions, rename the
257 // rest, and build the compile callbacks.
258 std::map<SymbolStringPtr, std::pair<JITTargetAddress, JITSymbolFlags>>
259 StubCallbacksAndLinkages;
260 auto &TargetVSO = R.getTargetVSO();
261
262 for (auto &F : M->functions()) {
263 if (F.isDeclaration())
264 continue;
265
266 if (F.hasAvailableExternallyLinkage()) {
267 F.deleteBody();
Lang Hames7bd89702018-07-05 19:01:27 +0000268 F.setPersonalityFn(nullptr);
Lang Hames68c9b8d2018-06-18 18:01:43 +0000269 continue;
270 }
271
272 assert(F.hasName() && "Function should have a name");
Lang Hames6a941342018-06-26 21:35:48 +0000273 std::string StubUnmangledName = F.getName();
Lang Hames68c9b8d2018-06-18 18:01:43 +0000274 F.setName(F.getName() + "$body");
Lang Hames6a941342018-06-26 21:35:48 +0000275 auto StubDecl = cloneFunctionDecl(*M, F);
276 StubDecl->setName(StubUnmangledName);
Lang Hames7bd89702018-07-05 19:01:27 +0000277 StubDecl->setPersonalityFn(nullptr);
278 StubDecl->setLinkage(GlobalValue::ExternalLinkage);
Lang Hames6a941342018-06-26 21:35:48 +0000279 F.replaceAllUsesWith(StubDecl);
Lang Hames7bd89702018-07-05 19:01:27 +0000280
Lang Hames6a941342018-06-26 21:35:48 +0000281 auto StubName = Mangle(StubUnmangledName);
Lang Hames68c9b8d2018-06-18 18:01:43 +0000282 auto BodyName = Mangle(F.getName());
283 if (auto CallbackAddr = CCMgr.getCompileCallback(
284 [BodyName, &TargetVSO, &ES]() -> JITTargetAddress {
285 if (auto Sym = lookup({&TargetVSO}, BodyName))
286 return Sym->getAddress();
287 else {
288 ES.reportError(Sym.takeError());
289 return 0;
290 }
291 })) {
292 auto Flags = JITSymbolFlags::fromGlobalValue(F);
293 Flags &= ~JITSymbolFlags::Weak;
294 StubCallbacksAndLinkages[std::move(StubName)] =
295 std::make_pair(*CallbackAddr, Flags);
296 } else {
297 ES.reportError(CallbackAddr.takeError());
298 R.failMaterialization();
299 return;
300 }
301 }
302
303 // Build the stub inits map.
304 IndirectStubsManager::StubInitsMap StubInits;
305 for (auto &KV : StubCallbacksAndLinkages)
306 StubInits[*KV.first] = KV.second;
307
308 // Build the function-body-extracting materialization unit.
Lang Hames6a941342018-06-26 21:35:48 +0000309 auto SR = GetSymbolResolver(K);
Lang Hames68c9b8d2018-06-18 18:01:43 +0000310 if (auto Err = R.getTargetVSO().define(
311 llvm::make_unique<ExtractingIRMaterializationUnit>(
Lang Hames6a941342018-06-26 21:35:48 +0000312 ES, *this, std::move(M), SR))) {
Lang Hames68c9b8d2018-06-18 18:01:43 +0000313 ES.reportError(std::move(Err));
314 R.failMaterialization();
315 return;
316 }
317
Lang Hames6a941342018-06-26 21:35:48 +0000318 // Replace the fallback symbol resolver: We will re-use M's VModuleKey for
319 // the GlobalsModule.
320 SetSymbolResolver(K, SR);
321
Lang Hames68c9b8d2018-06-18 18:01:43 +0000322 // Build the stubs.
323 // FIXME: Remove function bodies materialization unit if stub creation fails.
324 auto &StubsMgr = getStubsManager(TargetVSO);
325 if (auto Err = StubsMgr.createStubs(StubInits)) {
326 ES.reportError(std::move(Err));
327 R.failMaterialization();
328 return;
329 }
330
331 // Resolve and finalize stubs.
332 SymbolMap ResolvedStubs;
333 for (auto &KV : StubCallbacksAndLinkages) {
334 if (auto Sym = StubsMgr.findStub(*KV.first, false))
335 ResolvedStubs[KV.first] = Sym;
336 else
337 llvm_unreachable("Stub went missing");
338 }
339
340 R.resolve(ResolvedStubs);
341
342 BaseLayer.emit(std::move(R), std::move(K), std::move(GlobalsModule));
343}
344
345IndirectStubsManager &CompileOnDemandLayer2::getStubsManager(const VSO &V) {
346 std::lock_guard<std::mutex> Lock(CODLayerMutex);
347 StubManagersMap::iterator I = StubsMgrs.find(&V);
348 if (I == StubsMgrs.end())
349 I = StubsMgrs.insert(std::make_pair(&V, BuildIndirectStubsManager())).first;
350 return *I->second;
351}
352
Lang Hames68c9b8d2018-06-18 18:01:43 +0000353void CompileOnDemandLayer2::emitExtractedFunctionsModule(
354 MaterializationResponsibility R, std::unique_ptr<Module> M,
355 std::shared_ptr<SymbolResolver> Resolver) {
356 auto &TargetVSO = R.getTargetVSO();
357 auto K = getExecutionSession().allocateVModule();
358
359 auto ExtractedFunctionsResolver = createSymbolResolver(
360 [=](SymbolFlagsMap &Flags, const SymbolNameSet &Symbols) {
361 return Resolver->lookupFlags(Flags, Symbols);
362 },
363 [=, &TargetVSO](std::shared_ptr<AsynchronousSymbolQuery> Query,
364 SymbolNameSet Symbols) {
365 auto RemainingSymbols = TargetVSO.lookup(Query, std::move(Symbols));
366 return Resolver->lookup(std::move(Query), std::move(RemainingSymbols));
367 });
368
369 SetSymbolResolver(K, std::move(ExtractedFunctionsResolver));
370 BaseLayer.emit(std::move(R), std::move(K), std::move(M));
371}
372
373} // end namespace orc
374} // end namespace llvm