1 //===----- 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 14 using namespace llvm; 15 using namespace llvm::orc; 16 17 static ThreadSafeModule extractSubModule(ThreadSafeModule &TSM, 18 StringRef Suffix, 19 GVPredicate ShouldExtract) { 20 21 auto DeleteExtractedDefs = [](GlobalValue &GV) { 22 // Bump the linkage: this global will be provided by the external module. 23 GV.setLinkage(GlobalValue::ExternalLinkage); 24 25 // Delete the definition in the source module. 26 if (isa<Function>(GV)) { 27 auto &F = cast<Function>(GV); 28 F.deleteBody(); 29 F.setPersonalityFn(nullptr); 30 } else if (isa<GlobalVariable>(GV)) { 31 cast<GlobalVariable>(GV).setInitializer(nullptr); 32 } else if (isa<GlobalAlias>(GV)) { 33 // We need to turn deleted aliases into function or variable decls based 34 // on the type of their aliasee. 35 auto &A = cast<GlobalAlias>(GV); 36 Constant *Aliasee = A.getAliasee(); 37 assert(A.hasName() && "Anonymous alias?"); 38 assert(Aliasee->hasName() && "Anonymous aliasee"); 39 std::string AliasName = A.getName(); 40 41 if (isa<Function>(Aliasee)) { 42 auto *F = cloneFunctionDecl(*A.getParent(), *cast<Function>(Aliasee)); 43 A.replaceAllUsesWith(F); 44 A.eraseFromParent(); 45 F->setName(AliasName); 46 } else if (isa<GlobalVariable>(Aliasee)) { 47 auto *G = cloneGlobalVariableDecl(*A.getParent(), 48 *cast<GlobalVariable>(Aliasee)); 49 A.replaceAllUsesWith(G); 50 A.eraseFromParent(); 51 G->setName(AliasName); 52 } else 53 llvm_unreachable("Alias to unsupported type"); 54 } else 55 llvm_unreachable("Unsupported global type"); 56 }; 57 58 auto NewTSMod = cloneToNewContext(TSM, ShouldExtract, DeleteExtractedDefs); 59 auto &M = *NewTSMod.getModule(); 60 M.setModuleIdentifier((M.getModuleIdentifier() + Suffix).str()); 61 62 return NewTSMod; 63 } 64 65 namespace llvm { 66 namespace orc { 67 68 class PartitioningIRMaterializationUnit : public IRMaterializationUnit { 69 public: 70 PartitioningIRMaterializationUnit(ExecutionSession &ES, ThreadSafeModule TSM, 71 CompileOnDemandLayer2 &Parent) 72 : IRMaterializationUnit(ES, std::move(TSM)), Parent(Parent) {} 73 74 PartitioningIRMaterializationUnit( 75 ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags, 76 SymbolNameToDefinitionMap SymbolToDefinition, 77 CompileOnDemandLayer2 &Parent) 78 : IRMaterializationUnit(std::move(TSM), std::move(SymbolFlags), 79 std::move(SymbolToDefinition)), 80 Parent(Parent) {} 81 82 private: 83 void materialize(MaterializationResponsibility R) override { 84 Parent.emitPartition(std::move(R), std::move(TSM), 85 std::move(SymbolToDefinition)); 86 } 87 88 void discard(const JITDylib &V, const SymbolStringPtr &Name) override { 89 // All original symbols were materialized by the CODLayer and should be 90 // final. The function bodies provided by M should never be overridden. 91 llvm_unreachable("Discard should never be called on an " 92 "ExtractingIRMaterializationUnit"); 93 } 94 95 mutable std::mutex SourceModuleMutex; 96 CompileOnDemandLayer2 &Parent; 97 }; 98 99 Optional<CompileOnDemandLayer2::GlobalValueSet> 100 CompileOnDemandLayer2::compileRequested(GlobalValueSet Requested) { 101 return std::move(Requested); 102 } 103 104 Optional<CompileOnDemandLayer2::GlobalValueSet> 105 CompileOnDemandLayer2::compileWholeModule(GlobalValueSet Requested) { 106 return None; 107 } 108 109 CompileOnDemandLayer2::CompileOnDemandLayer2( 110 ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr, 111 IndirectStubsManagerBuilder BuildIndirectStubsManager) 112 : IRLayer(ES), BaseLayer(BaseLayer), LCTMgr(LCTMgr), 113 BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {} 114 115 void CompileOnDemandLayer2::setPartitionFunction(PartitionFunction Partition) { 116 this->Partition = std::move(Partition); 117 } 118 119 void CompileOnDemandLayer2::emit(MaterializationResponsibility R, VModuleKey K, 120 ThreadSafeModule TSM) { 121 assert(TSM.getModule() && "Null module"); 122 123 auto &ES = getExecutionSession(); 124 auto &M = *TSM.getModule(); 125 126 // First, do some cleanup on the module: 127 cleanUpModule(M); 128 129 // Now sort the callables and non-callables, build re-exports and lodge the 130 // actual module with the implementation dylib. 131 auto &PDR = getPerDylibResources(R.getTargetJITDylib()); 132 133 MangleAndInterner Mangle(ES, M.getDataLayout()); 134 SymbolAliasMap NonCallables; 135 SymbolAliasMap Callables; 136 for (auto &GV : M.global_values()) { 137 if (GV.isDeclaration() || GV.hasLocalLinkage() || GV.hasAppendingLinkage()) 138 continue; 139 140 auto Name = Mangle(GV.getName()); 141 auto Flags = JITSymbolFlags::fromGlobalValue(GV); 142 if (Flags.isCallable()) 143 Callables[Name] = SymbolAliasMapEntry(Name, Flags); 144 else 145 NonCallables[Name] = SymbolAliasMapEntry(Name, Flags); 146 } 147 148 // Create a partitioning materialization unit and lodge it with the 149 // implementation dylib. 150 if (auto Err = PDR.getImplDylib().define( 151 llvm::make_unique<PartitioningIRMaterializationUnit>( 152 ES, std::move(TSM), *this))) { 153 ES.reportError(std::move(Err)); 154 R.failMaterialization(); 155 return; 156 } 157 158 R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables))); 159 R.replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(), 160 std::move(Callables))); 161 } 162 163 CompileOnDemandLayer2::PerDylibResources & 164 CompileOnDemandLayer2::getPerDylibResources(JITDylib &TargetD) { 165 auto I = DylibResources.find(&TargetD); 166 if (I == DylibResources.end()) { 167 auto &ImplD = 168 getExecutionSession().createJITDylib(TargetD.getName() + ".impl"); 169 TargetD.withSearchOrderDo([&](const JITDylibList &TargetSearchOrder) { 170 ImplD.setSearchOrder(TargetSearchOrder, false); 171 }); 172 PerDylibResources PDR(ImplD, BuildIndirectStubsManager()); 173 I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first; 174 } 175 176 return I->second; 177 } 178 179 void CompileOnDemandLayer2::cleanUpModule(Module &M) { 180 for (auto &F : M.functions()) { 181 if (F.isDeclaration()) 182 continue; 183 184 if (F.hasAvailableExternallyLinkage()) { 185 F.deleteBody(); 186 F.setPersonalityFn(nullptr); 187 continue; 188 } 189 } 190 } 191 192 void CompileOnDemandLayer2::expandPartition(GlobalValueSet &Partition) { 193 // Expands the partition to ensure the following rules hold: 194 // (1) If any alias is in the partition, its aliasee is also in the partition. 195 // (2) If any aliasee is in the partition, its aliases are also in the 196 // partiton. 197 // (3) If any global variable is in the partition then all global variables 198 // are in the partition. 199 assert(!Partition.empty() && "Unexpected empty partition"); 200 201 const Module &M = *(*Partition.begin())->getParent(); 202 bool ContainsGlobalVariables = false; 203 std::vector<const GlobalValue *> GVsToAdd; 204 205 for (auto *GV : Partition) 206 if (isa<GlobalAlias>(GV)) 207 GVsToAdd.push_back( 208 cast<GlobalValue>(cast<GlobalAlias>(GV)->getAliasee())); 209 else if (isa<GlobalVariable>(GV)) 210 ContainsGlobalVariables = true; 211 212 for (auto &A : M.aliases()) 213 if (Partition.count(cast<GlobalValue>(A.getAliasee()))) 214 GVsToAdd.push_back(&A); 215 216 if (ContainsGlobalVariables) 217 for (auto &G : M.globals()) 218 GVsToAdd.push_back(&G); 219 220 for (auto *GV : GVsToAdd) 221 Partition.insert(GV); 222 } 223 224 void CompileOnDemandLayer2::emitPartition( 225 MaterializationResponsibility R, ThreadSafeModule TSM, 226 IRMaterializationUnit::SymbolNameToDefinitionMap Defs) { 227 228 // FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the 229 // extracted module key, extracted module, and source module key 230 // together. This could be used, for example, to provide a specific 231 // memory manager instance to the linking layer. 232 233 auto &ES = getExecutionSession(); 234 235 GlobalValueSet RequestedGVs; 236 for (auto &Name : R.getRequestedSymbols()) { 237 assert(Defs.count(Name) && "No definition for symbol"); 238 RequestedGVs.insert(Defs[Name]); 239 } 240 241 auto GVsToExtract = Partition(RequestedGVs); 242 243 // Take a 'None' partition to mean the whole module (as opposed to an empty 244 // partition, which means "materialize nothing"). Emit the whole module 245 // unmodified to the base layer. 246 if (GVsToExtract == None) { 247 Defs.clear(); 248 BaseLayer.emit(std::move(R), ES.allocateVModule(), std::move(TSM)); 249 return; 250 } 251 252 // If the partition is empty, return the whole module to the symbol table. 253 if (GVsToExtract->empty()) { 254 R.replace(llvm::make_unique<PartitioningIRMaterializationUnit>( 255 std::move(TSM), R.getSymbols(), std::move(Defs), *this)); 256 return; 257 } 258 259 // Ok -- we actually need to partition the symbols. Promote the symbol 260 // linkages/names. 261 // FIXME: We apply this once per partitioning. It's safe, but overkill. 262 { 263 auto PromotedGlobals = PromoteSymbols(*TSM.getModule()); 264 if (!PromotedGlobals.empty()) { 265 MangleAndInterner Mangle(ES, TSM.getModule()->getDataLayout()); 266 SymbolFlagsMap SymbolFlags; 267 for (auto &GV : PromotedGlobals) 268 SymbolFlags[Mangle(GV->getName())] = 269 JITSymbolFlags::fromGlobalValue(*GV); 270 if (auto Err = R.defineMaterializing(SymbolFlags)) { 271 ES.reportError(std::move(Err)); 272 R.failMaterialization(); 273 return; 274 } 275 } 276 } 277 278 expandPartition(*GVsToExtract); 279 280 // Extract the requested partiton (plus any necessary aliases) and 281 // put the rest back into the impl dylib. 282 auto ShouldExtract = [&](const GlobalValue &GV) -> bool { 283 return GVsToExtract->count(&GV); 284 }; 285 286 auto ExtractedTSM = extractSubModule(TSM, ".submodule", ShouldExtract); 287 R.replace(llvm::make_unique<PartitioningIRMaterializationUnit>( 288 ES, std::move(TSM), *this)); 289 290 BaseLayer.emit(std::move(R), ES.allocateVModule(), std::move(ExtractedTSM)); 291 } 292 293 } // end namespace orc 294 } // end namespace llvm 295