10b57cec5SDimitry Andric //===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
105ffd83dbSDimitry Andric #include "llvm/ADT/Hashing.h"
115ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
120b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
130b57cec5SDimitry Andric #include "llvm/IR/Module.h"
145ffd83dbSDimitry Andric #include "llvm/Support/FormatVariadic.h"
15fe6060f1SDimitry Andric #include <string>
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric using namespace llvm;
180b57cec5SDimitry Andric using namespace llvm::orc;
190b57cec5SDimitry Andric
extractSubModule(ThreadSafeModule & TSM,StringRef Suffix,GVPredicate ShouldExtract)200b57cec5SDimitry Andric static ThreadSafeModule extractSubModule(ThreadSafeModule &TSM,
210b57cec5SDimitry Andric StringRef Suffix,
220b57cec5SDimitry Andric GVPredicate ShouldExtract) {
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric auto DeleteExtractedDefs = [](GlobalValue &GV) {
250b57cec5SDimitry Andric // Bump the linkage: this global will be provided by the external module.
260b57cec5SDimitry Andric GV.setLinkage(GlobalValue::ExternalLinkage);
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric // Delete the definition in the source module.
290b57cec5SDimitry Andric if (isa<Function>(GV)) {
300b57cec5SDimitry Andric auto &F = cast<Function>(GV);
310b57cec5SDimitry Andric F.deleteBody();
320b57cec5SDimitry Andric F.setPersonalityFn(nullptr);
330b57cec5SDimitry Andric } else if (isa<GlobalVariable>(GV)) {
340b57cec5SDimitry Andric cast<GlobalVariable>(GV).setInitializer(nullptr);
350b57cec5SDimitry Andric } else if (isa<GlobalAlias>(GV)) {
360b57cec5SDimitry Andric // We need to turn deleted aliases into function or variable decls based
370b57cec5SDimitry Andric // on the type of their aliasee.
380b57cec5SDimitry Andric auto &A = cast<GlobalAlias>(GV);
390b57cec5SDimitry Andric Constant *Aliasee = A.getAliasee();
400b57cec5SDimitry Andric assert(A.hasName() && "Anonymous alias?");
410b57cec5SDimitry Andric assert(Aliasee->hasName() && "Anonymous aliasee");
425ffd83dbSDimitry Andric std::string AliasName = std::string(A.getName());
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric if (isa<Function>(Aliasee)) {
450b57cec5SDimitry Andric auto *F = cloneFunctionDecl(*A.getParent(), *cast<Function>(Aliasee));
460b57cec5SDimitry Andric A.replaceAllUsesWith(F);
470b57cec5SDimitry Andric A.eraseFromParent();
480b57cec5SDimitry Andric F->setName(AliasName);
490b57cec5SDimitry Andric } else if (isa<GlobalVariable>(Aliasee)) {
500b57cec5SDimitry Andric auto *G = cloneGlobalVariableDecl(*A.getParent(),
510b57cec5SDimitry Andric *cast<GlobalVariable>(Aliasee));
520b57cec5SDimitry Andric A.replaceAllUsesWith(G);
530b57cec5SDimitry Andric A.eraseFromParent();
540b57cec5SDimitry Andric G->setName(AliasName);
550b57cec5SDimitry Andric } else
560b57cec5SDimitry Andric llvm_unreachable("Alias to unsupported type");
570b57cec5SDimitry Andric } else
580b57cec5SDimitry Andric llvm_unreachable("Unsupported global type");
590b57cec5SDimitry Andric };
600b57cec5SDimitry Andric
618bcb0991SDimitry Andric auto NewTSM = cloneToNewContext(TSM, ShouldExtract, DeleteExtractedDefs);
628bcb0991SDimitry Andric NewTSM.withModuleDo([&](Module &M) {
630b57cec5SDimitry Andric M.setModuleIdentifier((M.getModuleIdentifier() + Suffix).str());
648bcb0991SDimitry Andric });
650b57cec5SDimitry Andric
668bcb0991SDimitry Andric return NewTSM;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric namespace llvm {
700b57cec5SDimitry Andric namespace orc {
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
730b57cec5SDimitry Andric public:
PartitioningIRMaterializationUnit(ExecutionSession & ES,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM,CompileOnDemandLayer & Parent)7413138422SDimitry Andric PartitioningIRMaterializationUnit(ExecutionSession &ES,
755ffd83dbSDimitry Andric const IRSymbolMapper::ManglingOptions &MO,
76e8d8bef9SDimitry Andric ThreadSafeModule TSM,
7713138422SDimitry Andric CompileOnDemandLayer &Parent)
78e8d8bef9SDimitry Andric : IRMaterializationUnit(ES, MO, std::move(TSM)), Parent(Parent) {}
790b57cec5SDimitry Andric
PartitioningIRMaterializationUnit(ThreadSafeModule TSM,Interface I,SymbolNameToDefinitionMap SymbolToDefinition,CompileOnDemandLayer & Parent)800b57cec5SDimitry Andric PartitioningIRMaterializationUnit(
810eae32dcSDimitry Andric ThreadSafeModule TSM, Interface I,
820eae32dcSDimitry Andric SymbolNameToDefinitionMap SymbolToDefinition,
830b57cec5SDimitry Andric CompileOnDemandLayer &Parent)
840eae32dcSDimitry Andric : IRMaterializationUnit(std::move(TSM), std::move(I),
850b57cec5SDimitry Andric std::move(SymbolToDefinition)),
860b57cec5SDimitry Andric Parent(Parent) {}
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric private:
materialize(std::unique_ptr<MaterializationResponsibility> R)89e8d8bef9SDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
900b57cec5SDimitry Andric Parent.emitPartition(std::move(R), std::move(TSM),
910b57cec5SDimitry Andric std::move(SymbolToDefinition));
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
discard(const JITDylib & V,const SymbolStringPtr & Name)940b57cec5SDimitry Andric void discard(const JITDylib &V, const SymbolStringPtr &Name) override {
950b57cec5SDimitry Andric // All original symbols were materialized by the CODLayer and should be
960b57cec5SDimitry Andric // final. The function bodies provided by M should never be overridden.
970b57cec5SDimitry Andric llvm_unreachable("Discard should never be called on an "
980b57cec5SDimitry Andric "ExtractingIRMaterializationUnit");
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric mutable std::mutex SourceModuleMutex;
1020b57cec5SDimitry Andric CompileOnDemandLayer &Parent;
1030b57cec5SDimitry Andric };
1040b57cec5SDimitry Andric
105*bdd1243dSDimitry Andric std::optional<CompileOnDemandLayer::GlobalValueSet>
compileRequested(GlobalValueSet Requested)1060b57cec5SDimitry Andric CompileOnDemandLayer::compileRequested(GlobalValueSet Requested) {
1070b57cec5SDimitry Andric return std::move(Requested);
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
110*bdd1243dSDimitry Andric std::optional<CompileOnDemandLayer::GlobalValueSet>
compileWholeModule(GlobalValueSet Requested)1110b57cec5SDimitry Andric CompileOnDemandLayer::compileWholeModule(GlobalValueSet Requested) {
112*bdd1243dSDimitry Andric return std::nullopt;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
CompileOnDemandLayer(ExecutionSession & ES,IRLayer & BaseLayer,LazyCallThroughManager & LCTMgr,IndirectStubsManagerBuilder BuildIndirectStubsManager)1150b57cec5SDimitry Andric CompileOnDemandLayer::CompileOnDemandLayer(
1160b57cec5SDimitry Andric ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr,
1170b57cec5SDimitry Andric IndirectStubsManagerBuilder BuildIndirectStubsManager)
11813138422SDimitry Andric : IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
11913138422SDimitry Andric LCTMgr(LCTMgr),
1200b57cec5SDimitry Andric BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {}
1210b57cec5SDimitry Andric
setPartitionFunction(PartitionFunction Partition)1220b57cec5SDimitry Andric void CompileOnDemandLayer::setPartitionFunction(PartitionFunction Partition) {
1230b57cec5SDimitry Andric this->Partition = std::move(Partition);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric
setImplMap(ImplSymbolMap * Imp)1268bcb0991SDimitry Andric void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) {
1278bcb0991SDimitry Andric this->AliaseeImpls = Imp;
1288bcb0991SDimitry Andric }
emit(std::unique_ptr<MaterializationResponsibility> R,ThreadSafeModule TSM)129e8d8bef9SDimitry Andric void CompileOnDemandLayer::emit(
130e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM) {
1318bcb0991SDimitry Andric assert(TSM && "Null module");
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric auto &ES = getExecutionSession();
1340b57cec5SDimitry Andric
1358bcb0991SDimitry Andric // Sort the callables and non-callables, build re-exports and lodge the
1360b57cec5SDimitry Andric // actual module with the implementation dylib.
137e8d8bef9SDimitry Andric auto &PDR = getPerDylibResources(R->getTargetJITDylib());
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric SymbolAliasMap NonCallables;
1400b57cec5SDimitry Andric SymbolAliasMap Callables;
1418bcb0991SDimitry Andric TSM.withModuleDo([&](Module &M) {
1428bcb0991SDimitry Andric // First, do some cleanup on the module:
1438bcb0991SDimitry Andric cleanUpModule(M);
14413138422SDimitry Andric });
1458bcb0991SDimitry Andric
146e8d8bef9SDimitry Andric for (auto &KV : R->getSymbols()) {
14713138422SDimitry Andric auto &Name = KV.first;
14813138422SDimitry Andric auto &Flags = KV.second;
1490b57cec5SDimitry Andric if (Flags.isCallable())
1500b57cec5SDimitry Andric Callables[Name] = SymbolAliasMapEntry(Name, Flags);
1510b57cec5SDimitry Andric else
1520b57cec5SDimitry Andric NonCallables[Name] = SymbolAliasMapEntry(Name, Flags);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric // Create a partitioning materialization unit and lodge it with the
1560b57cec5SDimitry Andric // implementation dylib.
1570b57cec5SDimitry Andric if (auto Err = PDR.getImplDylib().define(
1588bcb0991SDimitry Andric std::make_unique<PartitioningIRMaterializationUnit>(
159e8d8bef9SDimitry Andric ES, *getManglingOptions(), std::move(TSM), *this))) {
1600b57cec5SDimitry Andric ES.reportError(std::move(Err));
161e8d8bef9SDimitry Andric R->failMaterialization();
1620b57cec5SDimitry Andric return;
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric
1655ffd83dbSDimitry Andric if (!NonCallables.empty())
166e8d8bef9SDimitry Andric if (auto Err =
167e8d8bef9SDimitry Andric R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
168e8d8bef9SDimitry Andric JITDylibLookupFlags::MatchAllSymbols))) {
169e8d8bef9SDimitry Andric getExecutionSession().reportError(std::move(Err));
170e8d8bef9SDimitry Andric R->failMaterialization();
171e8d8bef9SDimitry Andric return;
172e8d8bef9SDimitry Andric }
173e8d8bef9SDimitry Andric if (!Callables.empty()) {
174e8d8bef9SDimitry Andric if (auto Err = R->replace(
175e8d8bef9SDimitry Andric lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
176e8d8bef9SDimitry Andric std::move(Callables), AliaseeImpls))) {
177e8d8bef9SDimitry Andric getExecutionSession().reportError(std::move(Err));
178e8d8bef9SDimitry Andric R->failMaterialization();
179e8d8bef9SDimitry Andric return;
180e8d8bef9SDimitry Andric }
181e8d8bef9SDimitry Andric }
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric CompileOnDemandLayer::PerDylibResources &
getPerDylibResources(JITDylib & TargetD)1850b57cec5SDimitry Andric CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) {
186349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(CODLayerMutex);
187349cc55cSDimitry Andric
1880b57cec5SDimitry Andric auto I = DylibResources.find(&TargetD);
1890b57cec5SDimitry Andric if (I == DylibResources.end()) {
190480093f4SDimitry Andric auto &ImplD =
1915ffd83dbSDimitry Andric getExecutionSession().createBareJITDylib(TargetD.getName() + ".impl");
1925ffd83dbSDimitry Andric JITDylibSearchOrder NewLinkOrder;
1935ffd83dbSDimitry Andric TargetD.withLinkOrderDo([&](const JITDylibSearchOrder &TargetLinkOrder) {
1945ffd83dbSDimitry Andric NewLinkOrder = TargetLinkOrder;
1955ffd83dbSDimitry Andric });
1965ffd83dbSDimitry Andric
1975ffd83dbSDimitry Andric assert(!NewLinkOrder.empty() && NewLinkOrder.front().first == &TargetD &&
1985ffd83dbSDimitry Andric NewLinkOrder.front().second ==
199480093f4SDimitry Andric JITDylibLookupFlags::MatchAllSymbols &&
2000b57cec5SDimitry Andric "TargetD must be at the front of its own search order and match "
2010b57cec5SDimitry Andric "non-exported symbol");
2025ffd83dbSDimitry Andric NewLinkOrder.insert(std::next(NewLinkOrder.begin()),
203480093f4SDimitry Andric {&ImplD, JITDylibLookupFlags::MatchAllSymbols});
2045ffd83dbSDimitry Andric ImplD.setLinkOrder(NewLinkOrder, false);
2055ffd83dbSDimitry Andric TargetD.setLinkOrder(std::move(NewLinkOrder), false);
2065ffd83dbSDimitry Andric
2070b57cec5SDimitry Andric PerDylibResources PDR(ImplD, BuildIndirectStubsManager());
2080b57cec5SDimitry Andric I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric return I->second;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
cleanUpModule(Module & M)2140b57cec5SDimitry Andric void CompileOnDemandLayer::cleanUpModule(Module &M) {
2150b57cec5SDimitry Andric for (auto &F : M.functions()) {
2160b57cec5SDimitry Andric if (F.isDeclaration())
2170b57cec5SDimitry Andric continue;
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric if (F.hasAvailableExternallyLinkage()) {
2200b57cec5SDimitry Andric F.deleteBody();
2210b57cec5SDimitry Andric F.setPersonalityFn(nullptr);
2220b57cec5SDimitry Andric continue;
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric
expandPartition(GlobalValueSet & Partition)2270b57cec5SDimitry Andric void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
2280b57cec5SDimitry Andric // Expands the partition to ensure the following rules hold:
2290b57cec5SDimitry Andric // (1) If any alias is in the partition, its aliasee is also in the partition.
2300b57cec5SDimitry Andric // (2) If any aliasee is in the partition, its aliases are also in the
2310b57cec5SDimitry Andric // partiton.
2320b57cec5SDimitry Andric // (3) If any global variable is in the partition then all global variables
2330b57cec5SDimitry Andric // are in the partition.
2340b57cec5SDimitry Andric assert(!Partition.empty() && "Unexpected empty partition");
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric const Module &M = *(*Partition.begin())->getParent();
2370b57cec5SDimitry Andric bool ContainsGlobalVariables = false;
2380b57cec5SDimitry Andric std::vector<const GlobalValue *> GVsToAdd;
2390b57cec5SDimitry Andric
240*bdd1243dSDimitry Andric for (const auto *GV : Partition)
2410b57cec5SDimitry Andric if (isa<GlobalAlias>(GV))
2420b57cec5SDimitry Andric GVsToAdd.push_back(
2430b57cec5SDimitry Andric cast<GlobalValue>(cast<GlobalAlias>(GV)->getAliasee()));
2440b57cec5SDimitry Andric else if (isa<GlobalVariable>(GV))
2450b57cec5SDimitry Andric ContainsGlobalVariables = true;
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric for (auto &A : M.aliases())
2480b57cec5SDimitry Andric if (Partition.count(cast<GlobalValue>(A.getAliasee())))
2490b57cec5SDimitry Andric GVsToAdd.push_back(&A);
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric if (ContainsGlobalVariables)
2520b57cec5SDimitry Andric for (auto &G : M.globals())
2530b57cec5SDimitry Andric GVsToAdd.push_back(&G);
2540b57cec5SDimitry Andric
255*bdd1243dSDimitry Andric for (const auto *GV : GVsToAdd)
2560b57cec5SDimitry Andric Partition.insert(GV);
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric
emitPartition(std::unique_ptr<MaterializationResponsibility> R,ThreadSafeModule TSM,IRMaterializationUnit::SymbolNameToDefinitionMap Defs)2590b57cec5SDimitry Andric void CompileOnDemandLayer::emitPartition(
260e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM,
2610b57cec5SDimitry Andric IRMaterializationUnit::SymbolNameToDefinitionMap Defs) {
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric // FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the
2640b57cec5SDimitry Andric // extracted module key, extracted module, and source module key
2650b57cec5SDimitry Andric // together. This could be used, for example, to provide a specific
2660b57cec5SDimitry Andric // memory manager instance to the linking layer.
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric auto &ES = getExecutionSession();
2690b57cec5SDimitry Andric GlobalValueSet RequestedGVs;
270e8d8bef9SDimitry Andric for (auto &Name : R->getRequestedSymbols()) {
271e8d8bef9SDimitry Andric if (Name == R->getInitializerSymbol())
2725ffd83dbSDimitry Andric TSM.withModuleDo([&](Module &M) {
2735ffd83dbSDimitry Andric for (auto &GV : getStaticInitGVs(M))
2745ffd83dbSDimitry Andric RequestedGVs.insert(&GV);
2755ffd83dbSDimitry Andric });
2765ffd83dbSDimitry Andric else {
2770b57cec5SDimitry Andric assert(Defs.count(Name) && "No definition for symbol");
2780b57cec5SDimitry Andric RequestedGVs.insert(Defs[Name]);
2790b57cec5SDimitry Andric }
2805ffd83dbSDimitry Andric }
2810b57cec5SDimitry Andric
2828bcb0991SDimitry Andric /// Perform partitioning with the context lock held, since the partition
2838bcb0991SDimitry Andric /// function is allowed to access the globals to compute the partition.
2848bcb0991SDimitry Andric auto GVsToExtract =
2858bcb0991SDimitry Andric TSM.withModuleDo([&](Module &M) { return Partition(RequestedGVs); });
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andric // Take a 'None' partition to mean the whole module (as opposed to an empty
2880b57cec5SDimitry Andric // partition, which means "materialize nothing"). Emit the whole module
2890b57cec5SDimitry Andric // unmodified to the base layer.
290*bdd1243dSDimitry Andric if (GVsToExtract == std::nullopt) {
2910b57cec5SDimitry Andric Defs.clear();
2920b57cec5SDimitry Andric BaseLayer.emit(std::move(R), std::move(TSM));
2930b57cec5SDimitry Andric return;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric // If the partition is empty, return the whole module to the symbol table.
2970b57cec5SDimitry Andric if (GVsToExtract->empty()) {
298e8d8bef9SDimitry Andric if (auto Err =
299e8d8bef9SDimitry Andric R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
3000eae32dcSDimitry Andric std::move(TSM),
3010eae32dcSDimitry Andric MaterializationUnit::Interface(R->getSymbols(),
3020eae32dcSDimitry Andric R->getInitializerSymbol()),
303e8d8bef9SDimitry Andric std::move(Defs), *this))) {
304e8d8bef9SDimitry Andric getExecutionSession().reportError(std::move(Err));
305e8d8bef9SDimitry Andric R->failMaterialization();
306e8d8bef9SDimitry Andric return;
307e8d8bef9SDimitry Andric }
3080b57cec5SDimitry Andric return;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric
3110b57cec5SDimitry Andric // Ok -- we actually need to partition the symbols. Promote the symbol
3128bcb0991SDimitry Andric // linkages/names, expand the partition to include any required symbols
3138bcb0991SDimitry Andric // (i.e. symbols that can't be separated from our partition), and
3148bcb0991SDimitry Andric // then extract the partition.
3158bcb0991SDimitry Andric //
3168bcb0991SDimitry Andric // FIXME: We apply this promotion once per partitioning. It's safe, but
3178bcb0991SDimitry Andric // overkill.
3188bcb0991SDimitry Andric auto ExtractedTSM =
3198bcb0991SDimitry Andric TSM.withModuleDo([&](Module &M) -> Expected<ThreadSafeModule> {
3208bcb0991SDimitry Andric auto PromotedGlobals = PromoteSymbols(M);
3210b57cec5SDimitry Andric if (!PromotedGlobals.empty()) {
3225ffd83dbSDimitry Andric
3238bcb0991SDimitry Andric MangleAndInterner Mangle(ES, M.getDataLayout());
3240b57cec5SDimitry Andric SymbolFlagsMap SymbolFlags;
3255ffd83dbSDimitry Andric IRSymbolMapper::add(ES, *getManglingOptions(),
3265ffd83dbSDimitry Andric PromotedGlobals, SymbolFlags);
3275ffd83dbSDimitry Andric
328e8d8bef9SDimitry Andric if (auto Err = R->defineMaterializing(SymbolFlags))
3298bcb0991SDimitry Andric return std::move(Err);
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric expandPartition(*GVsToExtract);
3330b57cec5SDimitry Andric
3345ffd83dbSDimitry Andric // Submodule name is given by hashing the names of the globals.
3355ffd83dbSDimitry Andric std::string SubModuleName;
3365ffd83dbSDimitry Andric {
3375ffd83dbSDimitry Andric std::vector<const GlobalValue*> HashGVs;
3385ffd83dbSDimitry Andric HashGVs.reserve(GVsToExtract->size());
339*bdd1243dSDimitry Andric for (const auto *GV : *GVsToExtract)
3405ffd83dbSDimitry Andric HashGVs.push_back(GV);
3415ffd83dbSDimitry Andric llvm::sort(HashGVs, [](const GlobalValue *LHS, const GlobalValue *RHS) {
3425ffd83dbSDimitry Andric return LHS->getName() < RHS->getName();
3435ffd83dbSDimitry Andric });
3445ffd83dbSDimitry Andric hash_code HC(0);
345*bdd1243dSDimitry Andric for (const auto *GV : HashGVs) {
3465ffd83dbSDimitry Andric assert(GV->hasName() && "All GVs to extract should be named by now");
3475ffd83dbSDimitry Andric auto GVName = GV->getName();
3485ffd83dbSDimitry Andric HC = hash_combine(HC, hash_combine_range(GVName.begin(), GVName.end()));
3495ffd83dbSDimitry Andric }
3505ffd83dbSDimitry Andric raw_string_ostream(SubModuleName)
3515ffd83dbSDimitry Andric << ".submodule."
3525ffd83dbSDimitry Andric << formatv(sizeof(size_t) == 8 ? "{0:x16}" : "{0:x8}",
3535ffd83dbSDimitry Andric static_cast<size_t>(HC))
3545ffd83dbSDimitry Andric << ".ll";
3555ffd83dbSDimitry Andric }
3565ffd83dbSDimitry Andric
3570b57cec5SDimitry Andric // Extract the requested partiton (plus any necessary aliases) and
3580b57cec5SDimitry Andric // put the rest back into the impl dylib.
3590b57cec5SDimitry Andric auto ShouldExtract = [&](const GlobalValue &GV) -> bool {
3600b57cec5SDimitry Andric return GVsToExtract->count(&GV);
3610b57cec5SDimitry Andric };
3620b57cec5SDimitry Andric
3635ffd83dbSDimitry Andric return extractSubModule(TSM, SubModuleName , ShouldExtract);
3648bcb0991SDimitry Andric });
3650b57cec5SDimitry Andric
3668bcb0991SDimitry Andric if (!ExtractedTSM) {
3678bcb0991SDimitry Andric ES.reportError(ExtractedTSM.takeError());
368e8d8bef9SDimitry Andric R->failMaterialization();
3698bcb0991SDimitry Andric return;
3708bcb0991SDimitry Andric }
3718bcb0991SDimitry Andric
372e8d8bef9SDimitry Andric if (auto Err = R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
373e8d8bef9SDimitry Andric ES, *getManglingOptions(), std::move(TSM), *this))) {
374e8d8bef9SDimitry Andric ES.reportError(std::move(Err));
375e8d8bef9SDimitry Andric R->failMaterialization();
376e8d8bef9SDimitry Andric return;
377e8d8bef9SDimitry Andric }
3788bcb0991SDimitry Andric BaseLayer.emit(std::move(R), std::move(*ExtractedTSM));
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric
3810b57cec5SDimitry Andric } // end namespace orc
3820b57cec5SDimitry Andric } // end namespace llvm
383