168c9b8d6SLang Hames //===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===//
268c9b8d6SLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668c9b8d6SLang Hames //
768c9b8d6SLang Hames //===----------------------------------------------------------------------===//
868c9b8d6SLang Hames 
968c9b8d6SLang Hames #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
101df947abSLang Hames #include "llvm/ADT/Hashing.h"
1185fb9976SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
1268c9b8d6SLang Hames #include "llvm/IR/Mangler.h"
1368c9b8d6SLang Hames #include "llvm/IR/Module.h"
141df947abSLang Hames #include "llvm/Support/FormatVariadic.h"
15367ec775SSimon Pilgrim #include <string>
1668c9b8d6SLang Hames 
1768c9b8d6SLang Hames using namespace llvm;
1868c9b8d6SLang Hames using namespace llvm::orc;
1968c9b8d6SLang Hames 
extractSubModule(ThreadSafeModule & TSM,StringRef Suffix,GVPredicate ShouldExtract)2098440293SLang Hames static ThreadSafeModule extractSubModule(ThreadSafeModule &TSM,
2198440293SLang Hames                                          StringRef Suffix,
2298440293SLang Hames                                          GVPredicate ShouldExtract) {
236a94134bSLang Hames 
2498440293SLang Hames   auto DeleteExtractedDefs = [](GlobalValue &GV) {
2598440293SLang Hames     // Bump the linkage: this global will be provided by the external module.
2698440293SLang Hames     GV.setLinkage(GlobalValue::ExternalLinkage);
276a94134bSLang Hames 
2898440293SLang Hames     // Delete the definition in the source module.
297bd89707SLang Hames     if (isa<Function>(GV)) {
308d76c711SLang Hames       auto &F = cast<Function>(GV);
317bd89707SLang Hames       F.deleteBody();
327bd89707SLang Hames       F.setPersonalityFn(nullptr);
337bd89707SLang Hames     } else if (isa<GlobalVariable>(GV)) {
348d76c711SLang Hames       cast<GlobalVariable>(GV).setInitializer(nullptr);
3598440293SLang Hames     } else if (isa<GlobalAlias>(GV)) {
3698440293SLang Hames       // We need to turn deleted aliases into function or variable decls based
3798440293SLang Hames       // on the type of their aliasee.
3898440293SLang Hames       auto &A = cast<GlobalAlias>(GV);
3998440293SLang Hames       Constant *Aliasee = A.getAliasee();
4098440293SLang Hames       assert(A.hasName() && "Anonymous alias?");
4198440293SLang Hames       assert(Aliasee->hasName() && "Anonymous aliasee");
42adcd0268SBenjamin Kramer       std::string AliasName = std::string(A.getName());
4398440293SLang Hames 
4498440293SLang Hames       if (isa<Function>(Aliasee)) {
4598440293SLang Hames         auto *F = cloneFunctionDecl(*A.getParent(), *cast<Function>(Aliasee));
4698440293SLang Hames         A.replaceAllUsesWith(F);
4798440293SLang Hames         A.eraseFromParent();
4898440293SLang Hames         F->setName(AliasName);
4998440293SLang Hames       } else if (isa<GlobalVariable>(Aliasee)) {
5098440293SLang Hames         auto *G = cloneGlobalVariableDecl(*A.getParent(),
5198440293SLang Hames                                           *cast<GlobalVariable>(Aliasee));
5298440293SLang Hames         A.replaceAllUsesWith(G);
5398440293SLang Hames         A.eraseFromParent();
5498440293SLang Hames         G->setName(AliasName);
5598440293SLang Hames       } else
5698440293SLang Hames         llvm_unreachable("Alias to unsupported type");
577bd89707SLang Hames     } else
587bd89707SLang Hames       llvm_unreachable("Unsupported global type");
598d76c711SLang Hames   };
608d76c711SLang Hames 
61809e9d1eSLang Hames   auto NewTSM = cloneToNewContext(TSM, ShouldExtract, DeleteExtractedDefs);
62809e9d1eSLang Hames   NewTSM.withModuleDo([&](Module &M) {
638d76c711SLang Hames     M.setModuleIdentifier((M.getModuleIdentifier() + Suffix).str());
64809e9d1eSLang Hames   });
658d76c711SLang Hames 
66809e9d1eSLang Hames   return NewTSM;
6768c9b8d6SLang Hames }
6868c9b8d6SLang Hames 
6968c9b8d6SLang Hames namespace llvm {
7068c9b8d6SLang Hames namespace orc {
7168c9b8d6SLang Hames 
7298440293SLang Hames class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
7368c9b8d6SLang Hames public:
PartitioningIRMaterializationUnit(ExecutionSession & ES,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM,CompileOnDemandLayer & Parent)74ce2207abSLang Hames   PartitioningIRMaterializationUnit(ExecutionSession &ES,
7585fb9976SLang Hames                                     const IRSymbolMapper::ManglingOptions &MO,
760aec49c8SLang Hames                                     ThreadSafeModule TSM,
77ce2207abSLang Hames                                     CompileOnDemandLayer &Parent)
780aec49c8SLang Hames       : IRMaterializationUnit(ES, MO, std::move(TSM)), Parent(Parent) {}
79fd0c1e71SLang Hames 
PartitioningIRMaterializationUnit(ThreadSafeModule TSM,Interface I,SymbolNameToDefinitionMap SymbolToDefinition,CompileOnDemandLayer & Parent)8098440293SLang Hames   PartitioningIRMaterializationUnit(
81*ae73f3fdSLang Hames       ThreadSafeModule TSM, Interface I,
82*ae73f3fdSLang Hames       SymbolNameToDefinitionMap SymbolToDefinition,
83079df9abSLang Hames       CompileOnDemandLayer &Parent)
84*ae73f3fdSLang Hames       : IRMaterializationUnit(std::move(TSM), std::move(I),
8568c9b8d6SLang Hames                               std::move(SymbolToDefinition)),
86fd0c1e71SLang Hames         Parent(Parent) {}
8768c9b8d6SLang Hames 
8868c9b8d6SLang Hames private:
materialize(std::unique_ptr<MaterializationResponsibility> R)897dcd0042SLang Hames   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
9098440293SLang Hames     Parent.emitPartition(std::move(R), std::move(TSM),
9198440293SLang Hames                          std::move(SymbolToDefinition));
9268c9b8d6SLang Hames   }
9368c9b8d6SLang Hames 
discard(const JITDylib & V,const SymbolStringPtr & Name)94cb5702c3SLang Hames   void discard(const JITDylib &V, const SymbolStringPtr &Name) override {
9568c9b8d6SLang Hames     // All original symbols were materialized by the CODLayer and should be
9668c9b8d6SLang Hames     // final. The function bodies provided by M should never be overridden.
9768c9b8d6SLang Hames     llvm_unreachable("Discard should never be called on an "
9868c9b8d6SLang Hames                      "ExtractingIRMaterializationUnit");
9968c9b8d6SLang Hames   }
10068c9b8d6SLang Hames 
1017bd89707SLang Hames   mutable std::mutex SourceModuleMutex;
102079df9abSLang Hames   CompileOnDemandLayer &Parent;
10368c9b8d6SLang Hames };
10468c9b8d6SLang Hames 
105079df9abSLang Hames Optional<CompileOnDemandLayer::GlobalValueSet>
compileRequested(GlobalValueSet Requested)106079df9abSLang Hames CompileOnDemandLayer::compileRequested(GlobalValueSet Requested) {
107c55cf4afSBill Wendling   return std::move(Requested);
10898440293SLang Hames }
10998440293SLang Hames 
110079df9abSLang Hames Optional<CompileOnDemandLayer::GlobalValueSet>
compileWholeModule(GlobalValueSet Requested)111079df9abSLang Hames CompileOnDemandLayer::compileWholeModule(GlobalValueSet Requested) {
11298440293SLang Hames   return None;
11398440293SLang Hames }
11498440293SLang Hames 
CompileOnDemandLayer(ExecutionSession & ES,IRLayer & BaseLayer,LazyCallThroughManager & LCTMgr,IndirectStubsManagerBuilder BuildIndirectStubsManager)115079df9abSLang Hames CompileOnDemandLayer::CompileOnDemandLayer(
116d8048675SLang Hames     ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr,
1178d76c711SLang Hames     IndirectStubsManagerBuilder BuildIndirectStubsManager)
118ce2207abSLang Hames     : IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
119ce2207abSLang Hames       LCTMgr(LCTMgr),
1208d76c711SLang Hames       BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {}
12168c9b8d6SLang Hames 
setPartitionFunction(PartitionFunction Partition)122079df9abSLang Hames void CompileOnDemandLayer::setPartitionFunction(PartitionFunction Partition) {
12398440293SLang Hames   this->Partition = std::move(Partition);
12468c9b8d6SLang Hames }
12568c9b8d6SLang Hames 
setImplMap(ImplSymbolMap * Imp)126f5c40cb9SPraveen Velliengiri void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) {
127f5c40cb9SPraveen Velliengiri   this->AliaseeImpls = Imp;
128f5c40cb9SPraveen Velliengiri }
emit(std::unique_ptr<MaterializationResponsibility> R,ThreadSafeModule TSM)1297dcd0042SLang Hames void CompileOnDemandLayer::emit(
1307dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM) {
131809e9d1eSLang Hames   assert(TSM && "Null module");
13298440293SLang Hames 
13368c9b8d6SLang Hames   auto &ES = getExecutionSession();
13468c9b8d6SLang Hames 
135809e9d1eSLang Hames   // Sort the callables and non-callables, build re-exports and lodge the
13698440293SLang Hames   // actual module with the implementation dylib.
1377dcd0042SLang Hames   auto &PDR = getPerDylibResources(R->getTargetJITDylib());
13868c9b8d6SLang Hames 
13998440293SLang Hames   SymbolAliasMap NonCallables;
14098440293SLang Hames   SymbolAliasMap Callables;
141809e9d1eSLang Hames   TSM.withModuleDo([&](Module &M) {
142809e9d1eSLang Hames     // First, do some cleanup on the module:
143809e9d1eSLang Hames     cleanUpModule(M);
144ce2207abSLang Hames   });
145809e9d1eSLang Hames 
1467dcd0042SLang Hames   for (auto &KV : R->getSymbols()) {
147ce2207abSLang Hames     auto &Name = KV.first;
148ce2207abSLang Hames     auto &Flags = KV.second;
14998440293SLang Hames     if (Flags.isCallable())
15098440293SLang Hames       Callables[Name] = SymbolAliasMapEntry(Name, Flags);
15198440293SLang Hames     else
15298440293SLang Hames       NonCallables[Name] = SymbolAliasMapEntry(Name, Flags);
15368c9b8d6SLang Hames   }
15468c9b8d6SLang Hames 
15598440293SLang Hames   // Create a partitioning materialization unit and lodge it with the
15698440293SLang Hames   // implementation dylib.
15798440293SLang Hames   if (auto Err = PDR.getImplDylib().define(
1580eaee545SJonas Devlieghere           std::make_unique<PartitioningIRMaterializationUnit>(
1590aec49c8SLang Hames               ES, *getManglingOptions(), std::move(TSM), *this))) {
16068c9b8d6SLang Hames     ES.reportError(std::move(Err));
1617dcd0042SLang Hames     R->failMaterialization();
16268c9b8d6SLang Hames     return;
16368c9b8d6SLang Hames   }
16468c9b8d6SLang Hames 
165a7b8393fSLang Hames   if (!NonCallables.empty())
1660aec49c8SLang Hames     if (auto Err =
1677dcd0042SLang Hames             R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
1680aec49c8SLang Hames                                  JITDylibLookupFlags::MatchAllSymbols))) {
1690aec49c8SLang Hames       getExecutionSession().reportError(std::move(Err));
1700aec49c8SLang Hames       R->failMaterialization();
1710aec49c8SLang Hames       return;
1720aec49c8SLang Hames     }
1730aec49c8SLang Hames   if (!Callables.empty()) {
1740aec49c8SLang Hames     if (auto Err = R->replace(
1750aec49c8SLang Hames             lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
1760aec49c8SLang Hames                           std::move(Callables), AliaseeImpls))) {
1770aec49c8SLang Hames       getExecutionSession().reportError(std::move(Err));
1780aec49c8SLang Hames       R->failMaterialization();
1790aec49c8SLang Hames       return;
1800aec49c8SLang Hames     }
1810aec49c8SLang Hames   }
18268c9b8d6SLang Hames }
18368c9b8d6SLang Hames 
184079df9abSLang Hames CompileOnDemandLayer::PerDylibResources &
getPerDylibResources(JITDylib & TargetD)185079df9abSLang Hames CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) {
1861ea8d125SLang Hames   std::lock_guard<std::mutex> Lock(CODLayerMutex);
1871ea8d125SLang Hames 
188d8048675SLang Hames   auto I = DylibResources.find(&TargetD);
189d8048675SLang Hames   if (I == DylibResources.end()) {
1904fc68b9bSLang Hames     auto &ImplD =
19185fb9976SLang Hames         getExecutionSession().createBareJITDylib(TargetD.getName() + ".impl");
192c66f8900SLang Hames     JITDylibSearchOrder NewLinkOrder;
193c66f8900SLang Hames     TargetD.withLinkOrderDo([&](const JITDylibSearchOrder &TargetLinkOrder) {
194c66f8900SLang Hames       NewLinkOrder = TargetLinkOrder;
19585fb9976SLang Hames     });
19685fb9976SLang Hames 
197c66f8900SLang Hames     assert(!NewLinkOrder.empty() && NewLinkOrder.front().first == &TargetD &&
198c66f8900SLang Hames            NewLinkOrder.front().second ==
199c66f8900SLang Hames                JITDylibLookupFlags::MatchAllSymbols &&
20023cb2e7fSLang Hames            "TargetD must be at the front of its own search order and match "
20123cb2e7fSLang Hames            "non-exported symbol");
202c66f8900SLang Hames     NewLinkOrder.insert(std::next(NewLinkOrder.begin()),
203674df13bSLang Hames                         {&ImplD, JITDylibLookupFlags::MatchAllSymbols});
204c66f8900SLang Hames     ImplD.setLinkOrder(NewLinkOrder, false);
205c66f8900SLang Hames     TargetD.setLinkOrder(std::move(NewLinkOrder), false);
20685fb9976SLang Hames 
207d8048675SLang Hames     PerDylibResources PDR(ImplD, BuildIndirectStubsManager());
208d8048675SLang Hames     I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;
209d8048675SLang Hames   }
210d8048675SLang Hames 
211d8048675SLang Hames   return I->second;
21268c9b8d6SLang Hames }
21368c9b8d6SLang Hames 
cleanUpModule(Module & M)214079df9abSLang Hames void CompileOnDemandLayer::cleanUpModule(Module &M) {
21598440293SLang Hames   for (auto &F : M.functions()) {
21698440293SLang Hames     if (F.isDeclaration())
21798440293SLang Hames       continue;
21898440293SLang Hames 
21998440293SLang Hames     if (F.hasAvailableExternallyLinkage()) {
22098440293SLang Hames       F.deleteBody();
22198440293SLang Hames       F.setPersonalityFn(nullptr);
22298440293SLang Hames       continue;
22398440293SLang Hames     }
22498440293SLang Hames   }
22598440293SLang Hames }
22698440293SLang Hames 
expandPartition(GlobalValueSet & Partition)227079df9abSLang Hames void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
22898440293SLang Hames   // Expands the partition to ensure the following rules hold:
22998440293SLang Hames   // (1) If any alias is in the partition, its aliasee is also in the partition.
23098440293SLang Hames   // (2) If any aliasee is in the partition, its aliases are also in the
23198440293SLang Hames   //     partiton.
23298440293SLang Hames   // (3) If any global variable is in the partition then all global variables
23398440293SLang Hames   //     are in the partition.
23498440293SLang Hames   assert(!Partition.empty() && "Unexpected empty partition");
23598440293SLang Hames 
23698440293SLang Hames   const Module &M = *(*Partition.begin())->getParent();
23798440293SLang Hames   bool ContainsGlobalVariables = false;
23898440293SLang Hames   std::vector<const GlobalValue *> GVsToAdd;
23998440293SLang Hames 
24098440293SLang Hames   for (auto *GV : Partition)
24198440293SLang Hames     if (isa<GlobalAlias>(GV))
24298440293SLang Hames       GVsToAdd.push_back(
24398440293SLang Hames           cast<GlobalValue>(cast<GlobalAlias>(GV)->getAliasee()));
24498440293SLang Hames     else if (isa<GlobalVariable>(GV))
24598440293SLang Hames       ContainsGlobalVariables = true;
24698440293SLang Hames 
24798440293SLang Hames   for (auto &A : M.aliases())
24898440293SLang Hames     if (Partition.count(cast<GlobalValue>(A.getAliasee())))
24998440293SLang Hames       GVsToAdd.push_back(&A);
25098440293SLang Hames 
25198440293SLang Hames   if (ContainsGlobalVariables)
25298440293SLang Hames     for (auto &G : M.globals())
25398440293SLang Hames       GVsToAdd.push_back(&G);
25498440293SLang Hames 
25598440293SLang Hames   for (auto *GV : GVsToAdd)
25698440293SLang Hames     Partition.insert(GV);
25798440293SLang Hames }
25898440293SLang Hames 
emitPartition(std::unique_ptr<MaterializationResponsibility> R,ThreadSafeModule TSM,IRMaterializationUnit::SymbolNameToDefinitionMap Defs)259079df9abSLang Hames void CompileOnDemandLayer::emitPartition(
2607dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM,
26198440293SLang Hames     IRMaterializationUnit::SymbolNameToDefinitionMap Defs) {
26298440293SLang Hames 
26398440293SLang Hames   // FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the
26498440293SLang Hames   //        extracted module key, extracted module, and source module key
26598440293SLang Hames   //        together. This could be used, for example, to provide a specific
26698440293SLang Hames   //        memory manager instance to the linking layer.
26798440293SLang Hames 
26898440293SLang Hames   auto &ES = getExecutionSession();
26998440293SLang Hames   GlobalValueSet RequestedGVs;
2707dcd0042SLang Hames   for (auto &Name : R->getRequestedSymbols()) {
2717dcd0042SLang Hames     if (Name == R->getInitializerSymbol())
27285fb9976SLang Hames       TSM.withModuleDo([&](Module &M) {
27385fb9976SLang Hames         for (auto &GV : getStaticInitGVs(M))
27485fb9976SLang Hames           RequestedGVs.insert(&GV);
27585fb9976SLang Hames       });
27685fb9976SLang Hames     else {
27798440293SLang Hames       assert(Defs.count(Name) && "No definition for symbol");
27898440293SLang Hames       RequestedGVs.insert(Defs[Name]);
27998440293SLang Hames     }
28085fb9976SLang Hames   }
28198440293SLang Hames 
282809e9d1eSLang Hames   /// Perform partitioning with the context lock held, since the partition
283809e9d1eSLang Hames   /// function is allowed to access the globals to compute the partition.
284809e9d1eSLang Hames   auto GVsToExtract =
285809e9d1eSLang Hames       TSM.withModuleDo([&](Module &M) { return Partition(RequestedGVs); });
28698440293SLang Hames 
28798440293SLang Hames   // Take a 'None' partition to mean the whole module (as opposed to an empty
28898440293SLang Hames   // partition, which means "materialize nothing"). Emit the whole module
28998440293SLang Hames   // unmodified to the base layer.
29098440293SLang Hames   if (GVsToExtract == None) {
29198440293SLang Hames     Defs.clear();
2928b94274fSLang Hames     BaseLayer.emit(std::move(R), std::move(TSM));
29398440293SLang Hames     return;
29498440293SLang Hames   }
29598440293SLang Hames 
29698440293SLang Hames   // If the partition is empty, return the whole module to the symbol table.
29798440293SLang Hames   if (GVsToExtract->empty()) {
2980aec49c8SLang Hames     if (auto Err =
2997dcd0042SLang Hames             R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
300*ae73f3fdSLang Hames                 std::move(TSM),
301*ae73f3fdSLang Hames                 MaterializationUnit::Interface(R->getSymbols(),
302*ae73f3fdSLang Hames                                                R->getInitializerSymbol()),
3030aec49c8SLang Hames                 std::move(Defs), *this))) {
3040aec49c8SLang Hames       getExecutionSession().reportError(std::move(Err));
3050aec49c8SLang Hames       R->failMaterialization();
3060aec49c8SLang Hames       return;
3070aec49c8SLang Hames     }
30898440293SLang Hames     return;
30998440293SLang Hames   }
31098440293SLang Hames 
311bf6603e9SLang Hames   // Ok -- we actually need to partition the symbols. Promote the symbol
312809e9d1eSLang Hames   // linkages/names, expand the partition to include any required symbols
313809e9d1eSLang Hames   // (i.e. symbols that can't be separated from our partition), and
314809e9d1eSLang Hames   // then extract the partition.
315809e9d1eSLang Hames   //
316809e9d1eSLang Hames   // FIXME: We apply this promotion once per partitioning. It's safe, but
317809e9d1eSLang Hames   // overkill.
318809e9d1eSLang Hames   auto ExtractedTSM =
319809e9d1eSLang Hames       TSM.withModuleDo([&](Module &M) -> Expected<ThreadSafeModule> {
320809e9d1eSLang Hames         auto PromotedGlobals = PromoteSymbols(M);
321bf6603e9SLang Hames         if (!PromotedGlobals.empty()) {
3221df947abSLang Hames 
323809e9d1eSLang Hames           MangleAndInterner Mangle(ES, M.getDataLayout());
324bf6603e9SLang Hames           SymbolFlagsMap SymbolFlags;
3251df947abSLang Hames           IRSymbolMapper::add(ES, *getManglingOptions(),
3261df947abSLang Hames                               PromotedGlobals, SymbolFlags);
3271df947abSLang Hames 
3287dcd0042SLang Hames           if (auto Err = R->defineMaterializing(SymbolFlags))
329c55cf4afSBill Wendling             return std::move(Err);
330bf6603e9SLang Hames         }
331bf6603e9SLang Hames 
33298440293SLang Hames         expandPartition(*GVsToExtract);
33398440293SLang Hames 
3341df947abSLang Hames         // Submodule name is given by hashing the names of the globals.
3351df947abSLang Hames         std::string SubModuleName;
3361df947abSLang Hames         {
3371df947abSLang Hames           std::vector<const GlobalValue*> HashGVs;
3381df947abSLang Hames           HashGVs.reserve(GVsToExtract->size());
3391df947abSLang Hames           for (auto *GV : *GVsToExtract)
3401df947abSLang Hames             HashGVs.push_back(GV);
3411df947abSLang Hames           llvm::sort(HashGVs, [](const GlobalValue *LHS, const GlobalValue *RHS) {
3421df947abSLang Hames               return LHS->getName() < RHS->getName();
3431df947abSLang Hames             });
3441df947abSLang Hames           hash_code HC(0);
3451df947abSLang Hames           for (auto *GV : HashGVs) {
3461df947abSLang Hames             assert(GV->hasName() && "All GVs to extract should be named by now");
3471df947abSLang Hames             auto GVName = GV->getName();
3481df947abSLang Hames             HC = hash_combine(HC, hash_combine_range(GVName.begin(), GVName.end()));
3491df947abSLang Hames           }
3501df947abSLang Hames           raw_string_ostream(SubModuleName)
3511df947abSLang Hames             << ".submodule."
3521df947abSLang Hames             << formatv(sizeof(size_t) == 8 ? "{0:x16}" : "{0:x8}",
3531df947abSLang Hames                        static_cast<size_t>(HC))
3541df947abSLang Hames             << ".ll";
3551df947abSLang Hames         }
3561df947abSLang Hames 
35798440293SLang Hames         // Extract the requested partiton (plus any necessary aliases) and
35898440293SLang Hames         // put the rest back into the impl dylib.
35998440293SLang Hames         auto ShouldExtract = [&](const GlobalValue &GV) -> bool {
36098440293SLang Hames           return GVsToExtract->count(&GV);
36198440293SLang Hames         };
36298440293SLang Hames 
3631df947abSLang Hames         return extractSubModule(TSM, SubModuleName , ShouldExtract);
364809e9d1eSLang Hames       });
365809e9d1eSLang Hames 
366809e9d1eSLang Hames   if (!ExtractedTSM) {
367809e9d1eSLang Hames     ES.reportError(ExtractedTSM.takeError());
3687dcd0042SLang Hames     R->failMaterialization();
369809e9d1eSLang Hames     return;
370809e9d1eSLang Hames   }
371809e9d1eSLang Hames 
3720aec49c8SLang Hames   if (auto Err = R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
3730aec49c8SLang Hames           ES, *getManglingOptions(), std::move(TSM), *this))) {
3740aec49c8SLang Hames     ES.reportError(std::move(Err));
3750aec49c8SLang Hames     R->failMaterialization();
3760aec49c8SLang Hames     return;
3770aec49c8SLang Hames   }
378809e9d1eSLang Hames   BaseLayer.emit(std::move(R), std::move(*ExtractedTSM));
37968c9b8d6SLang Hames }
38068c9b8d6SLang Hames 
38168c9b8d6SLang Hames } // end namespace orc
38268c9b8d6SLang Hames } // end namespace llvm
383