xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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