blob: 584f990976ac2a064fe85665a04e427c4becd9d5 [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"
11#include "llvm/IR/Mangler.h"
12#include "llvm/IR/Module.h"
13#include "llvm/Support/raw_ostream.h"
14
15using namespace llvm;
16using namespace llvm::orc;
17
18namespace {
19
20template <typename MaterializerFtor>
21class LambdaValueMaterializer final : public ValueMaterializer {
22public:
23 LambdaValueMaterializer(MaterializerFtor M) : M(std::move(M)) {}
24
25 Value *materialize(Value *V) final { return M(V); }
26
27private:
28 MaterializerFtor M;
29};
30
31template <typename MaterializerFtor>
32LambdaValueMaterializer<MaterializerFtor>
33createLambdaValueMaterializer(MaterializerFtor M) {
34 return LambdaValueMaterializer<MaterializerFtor>(std::move(M));
35}
36} // namespace
37
38static std::unique_ptr<Module> extractGlobals(Module &M) {
39 // FIXME: Add alias support.
40
41 if (M.global_empty() && M.alias_empty() && !M.getModuleFlagsMetadata())
42 return nullptr;
43
44 auto GlobalsModule = llvm::make_unique<Module>(
45 (M.getName() + ".globals").str(), M.getContext());
46 GlobalsModule->setDataLayout(M.getDataLayout());
47
48 ValueToValueMapTy VMap;
49
50 for (auto &GV : M.globals())
51 if (!GV.isDeclaration() && !VMap.count(&GV))
52 cloneGlobalVariableDecl(*GlobalsModule, GV, &VMap);
53
54 // Clone the module flags.
55 cloneModuleFlagsMetadata(*GlobalsModule, M, VMap);
56
57 auto Materializer = createLambdaValueMaterializer([&](Value *V) -> Value * {
58 if (auto *F = dyn_cast<Function>(V))
59 return cloneFunctionDecl(*GlobalsModule, *F);
60 return nullptr;
61 });
62
63 // Move the global variable initializers.
64 for (auto &GV : M.globals()) {
65 if (!GV.isDeclaration())
66 moveGlobalVariableInitializer(GV, VMap, &Materializer);
67 GV.setInitializer(nullptr);
68 }
69
70 return GlobalsModule;
71}
72
73namespace llvm {
74namespace orc {
75
76class ExtractingIRMaterializationUnit : public IRMaterializationUnit {
77public:
78 ExtractingIRMaterializationUnit(
79 ExecutionSession &ES, CompileOnDemandLayer2 &Parent,
80 std::unique_ptr<Module> M,
81 std::shared_ptr<SymbolResolver> BackingResolver)
82 : IRMaterializationUnit(ES, std::move(M)), Parent(Parent),
83 BackingResolver(std::move(BackingResolver)) {}
84
85 ExtractingIRMaterializationUnit(
86 std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
87 SymbolNameToDefinitionMap SymbolToDefinition,
88 CompileOnDemandLayer2 &Parent,
89 std::shared_ptr<SymbolResolver> BackingResolver)
90 : IRMaterializationUnit(std::move(M), std::move(SymbolFlags),
91 std::move(SymbolToDefinition)),
92 Parent(Parent), BackingResolver(std::move(BackingResolver)) {}
93
94private:
95 void materialize(MaterializationResponsibility R) override {
96 // FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the
97 // extracted module key, extracted module, and source module key
98 // together. This could be used, for example, to provide a specific
99 // memory manager instance to the linking layer.
100
101 // FIXME: The derived constructor should *only* look for the names of
102 // original function definitions in the target VSO. All other
103 // symbols should be looked up in the backing resolver.
104
105 // Find the functions that have been requested.
106 auto RequestedSymbols = R.getRequestedSymbols();
107
108 // Extract them into a new module.
109 auto ExtractedFunctionsModule =
110 Parent.extractFunctions(*M, RequestedSymbols, SymbolToDefinition);
111
112 // Build a new ExtractingIRMaterializationUnit to delegate the unrequested
113 // symbols to.
114 SymbolFlagsMap DelegatedSymbolFlags;
115 IRMaterializationUnit::SymbolNameToDefinitionMap
116 DelegatedSymbolToDefinition;
117 for (auto &KV : SymbolToDefinition) {
118 if (RequestedSymbols.count(KV.first))
119 continue;
120 DelegatedSymbolFlags[KV.first] =
121 JITSymbolFlags::fromGlobalValue(*KV.second);
122 DelegatedSymbolToDefinition[KV.first] = KV.second;
123 }
124
125 if (!DelegatedSymbolFlags.empty()) {
126 assert(DelegatedSymbolFlags.size() ==
127 DelegatedSymbolToDefinition.size() &&
128 "SymbolFlags and SymbolToDefinition should have the same number "
129 "of entries");
130 R.delegate(llvm::make_unique<ExtractingIRMaterializationUnit>(
131 std::move(M), std::move(DelegatedSymbolFlags),
132 std::move(DelegatedSymbolToDefinition), Parent, BackingResolver));
133 }
134
135 Parent.emitExtractedFunctionsModule(
136 std::move(R), std::move(ExtractedFunctionsModule), BackingResolver);
137 }
138
139 void discard(const VSO &V, SymbolStringPtr Name) override {
140 // All original symbols were materialized by the CODLayer and should be
141 // final. The function bodies provided by M should never be overridden.
142 llvm_unreachable("Discard should never be called on an "
143 "ExtractingIRMaterializationUnit");
144 }
145
146 CompileOnDemandLayer2 &Parent;
147 std::shared_ptr<SymbolResolver> BackingResolver;
148};
149
150CompileOnDemandLayer2::CompileOnDemandLayer2(
151 ExecutionSession &ES, IRLayer &BaseLayer, JITCompileCallbackManager &CCMgr,
152 IndirectStubsManagerBuilder BuildIndirectStubsManager,
153 GetSymbolResolverFunction GetSymbolResolver,
154 SetSymbolResolverFunction SetSymbolResolver,
155 GetAvailableContextFunction GetAvailableContext)
156 : IRLayer(ES), BaseLayer(BaseLayer), CCMgr(CCMgr),
157 BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)),
158 GetSymbolResolver(std::move(GetSymbolResolver)),
159 SetSymbolResolver(std::move(SetSymbolResolver)),
160 GetAvailableContext(std::move(GetAvailableContext)) {}
161
162Error CompileOnDemandLayer2::add(VSO &V, VModuleKey K,
163 std::unique_ptr<Module> M) {
164 makeAllSymbolsExternallyAccessible(*M);
165 return IRLayer::add(V, K, std::move(M));
166}
167
168void CompileOnDemandLayer2::emit(MaterializationResponsibility R, VModuleKey K,
169 std::unique_ptr<Module> M) {
170 auto &ES = getExecutionSession();
171 assert(M && "M should not be null");
172
173 for (auto &GV : M->global_values())
174 if (GV.hasWeakLinkage())
175 GV.setLinkage(GlobalValue::ExternalLinkage);
176
177 auto GlobalsModule = extractGlobals(*M);
178
179 MangleAndInterner Mangle(ES, M->getDataLayout());
180
181 // Delete the bodies of any available externally functions, rename the
182 // rest, and build the compile callbacks.
183 std::map<SymbolStringPtr, std::pair<JITTargetAddress, JITSymbolFlags>>
184 StubCallbacksAndLinkages;
185 auto &TargetVSO = R.getTargetVSO();
186
187 for (auto &F : M->functions()) {
188 if (F.isDeclaration())
189 continue;
190
191 if (F.hasAvailableExternallyLinkage()) {
192 F.deleteBody();
193 continue;
194 }
195
196 assert(F.hasName() && "Function should have a name");
197 auto StubName = Mangle(F.getName());
198 F.setName(F.getName() + "$body");
199 auto BodyName = Mangle(F.getName());
200 if (auto CallbackAddr = CCMgr.getCompileCallback(
201 [BodyName, &TargetVSO, &ES]() -> JITTargetAddress {
202 if (auto Sym = lookup({&TargetVSO}, BodyName))
203 return Sym->getAddress();
204 else {
205 ES.reportError(Sym.takeError());
206 return 0;
207 }
208 })) {
209 auto Flags = JITSymbolFlags::fromGlobalValue(F);
210 Flags &= ~JITSymbolFlags::Weak;
211 StubCallbacksAndLinkages[std::move(StubName)] =
212 std::make_pair(*CallbackAddr, Flags);
213 } else {
214 ES.reportError(CallbackAddr.takeError());
215 R.failMaterialization();
216 return;
217 }
218 }
219
220 // Build the stub inits map.
221 IndirectStubsManager::StubInitsMap StubInits;
222 for (auto &KV : StubCallbacksAndLinkages)
223 StubInits[*KV.first] = KV.second;
224
225 // Build the function-body-extracting materialization unit.
226 if (auto Err = R.getTargetVSO().define(
227 llvm::make_unique<ExtractingIRMaterializationUnit>(
228 ES, *this, std::move(M), GetSymbolResolver(K)))) {
229 ES.reportError(std::move(Err));
230 R.failMaterialization();
231 return;
232 }
233
234 // Build the stubs.
235 // FIXME: Remove function bodies materialization unit if stub creation fails.
236 auto &StubsMgr = getStubsManager(TargetVSO);
237 if (auto Err = StubsMgr.createStubs(StubInits)) {
238 ES.reportError(std::move(Err));
239 R.failMaterialization();
240 return;
241 }
242
243 // Resolve and finalize stubs.
244 SymbolMap ResolvedStubs;
245 for (auto &KV : StubCallbacksAndLinkages) {
246 if (auto Sym = StubsMgr.findStub(*KV.first, false))
247 ResolvedStubs[KV.first] = Sym;
248 else
249 llvm_unreachable("Stub went missing");
250 }
251
252 R.resolve(ResolvedStubs);
253
254 BaseLayer.emit(std::move(R), std::move(K), std::move(GlobalsModule));
255}
256
257IndirectStubsManager &CompileOnDemandLayer2::getStubsManager(const VSO &V) {
258 std::lock_guard<std::mutex> Lock(CODLayerMutex);
259 StubManagersMap::iterator I = StubsMgrs.find(&V);
260 if (I == StubsMgrs.end())
261 I = StubsMgrs.insert(std::make_pair(&V, BuildIndirectStubsManager())).first;
262 return *I->second;
263}
264
265std::unique_ptr<Module> CompileOnDemandLayer2::extractFunctions(
266 Module &M, const SymbolNameSet &SymbolNames,
267 const SymbolNameToDefinitionMap &SymbolToDefinition) {
268 assert(!SymbolNames.empty() && "Can not extract an empty function set");
269
270 std::string ExtractedModName;
271 {
272 raw_string_ostream ExtractedModNameStream(ExtractedModName);
273 ExtractedModNameStream << M.getName();
274 for (auto &Name : SymbolNames)
275 ExtractedModNameStream << "." << *Name;
276 }
277
278 auto ExtractedFunctionsModule =
279 llvm::make_unique<Module>(ExtractedModName, GetAvailableContext());
280 ExtractedFunctionsModule->setDataLayout(M.getDataLayout());
281
282 ValueToValueMapTy VMap;
283
284 auto Materializer = createLambdaValueMaterializer([&](Value *V) -> Value * {
285 if (auto *F = dyn_cast<Function>(V))
286 return cloneFunctionDecl(*ExtractedFunctionsModule, *F);
287 else if (auto *GV = dyn_cast<GlobalVariable>(V))
288 return cloneGlobalVariableDecl(*ExtractedFunctionsModule, *GV);
289 return nullptr;
290 });
291
292 std::vector<std::pair<Function *, Function *>> OrigToNew;
293 for (auto &FunctionName : SymbolNames) {
294 assert(SymbolToDefinition.count(FunctionName) &&
295 "No definition for symbol");
296 auto *OrigF = cast<Function>(SymbolToDefinition.find(FunctionName)->second);
297 auto *NewF = cloneFunctionDecl(*ExtractedFunctionsModule, *OrigF, &VMap);
298 OrigToNew.push_back(std::make_pair(OrigF, NewF));
299 }
300
301 for (auto &KV : OrigToNew)
302 moveFunctionBody(*KV.first, VMap, &Materializer, KV.second);
303
304 return ExtractedFunctionsModule;
305}
306
307void CompileOnDemandLayer2::emitExtractedFunctionsModule(
308 MaterializationResponsibility R, std::unique_ptr<Module> M,
309 std::shared_ptr<SymbolResolver> Resolver) {
310 auto &TargetVSO = R.getTargetVSO();
311 auto K = getExecutionSession().allocateVModule();
312
313 auto ExtractedFunctionsResolver = createSymbolResolver(
314 [=](SymbolFlagsMap &Flags, const SymbolNameSet &Symbols) {
315 return Resolver->lookupFlags(Flags, Symbols);
316 },
317 [=, &TargetVSO](std::shared_ptr<AsynchronousSymbolQuery> Query,
318 SymbolNameSet Symbols) {
319 auto RemainingSymbols = TargetVSO.lookup(Query, std::move(Symbols));
320 return Resolver->lookup(std::move(Query), std::move(RemainingSymbols));
321 });
322
323 SetSymbolResolver(K, std::move(ExtractedFunctionsResolver));
324 BaseLayer.emit(std::move(R), std::move(K), std::move(M));
325}
326
327} // end namespace orc
328} // end namespace llvm