11398a32eSPeter Collingbourne //===- ThinLTOBitcodeWriter.cpp - Bitcode writing pass for ThinLTO --------===// 21398a32eSPeter Collingbourne // 31398a32eSPeter Collingbourne // The LLVM Compiler Infrastructure 41398a32eSPeter Collingbourne // 51398a32eSPeter Collingbourne // This file is distributed under the University of Illinois Open Source 61398a32eSPeter Collingbourne // License. See LICENSE.TXT for details. 71398a32eSPeter Collingbourne // 81398a32eSPeter Collingbourne //===----------------------------------------------------------------------===// 91398a32eSPeter Collingbourne // 101398a32eSPeter Collingbourne // This pass prepares a module containing type metadata for ThinLTO by splitting 111398a32eSPeter Collingbourne // it into regular and thin LTO parts if possible, and writing both parts to 121398a32eSPeter Collingbourne // a multi-module bitcode file. Modules that do not contain type metadata are 131398a32eSPeter Collingbourne // written unmodified as a single module. 141398a32eSPeter Collingbourne // 151398a32eSPeter Collingbourne //===----------------------------------------------------------------------===// 161398a32eSPeter Collingbourne 17002c2d53SPeter Collingbourne #include "llvm/Analysis/BasicAliasAnalysis.h" 181398a32eSPeter Collingbourne #include "llvm/Analysis/ModuleSummaryAnalysis.h" 1994624acaSTeresa Johnson #include "llvm/Analysis/ProfileSummaryInfo.h" 201398a32eSPeter Collingbourne #include "llvm/Analysis/TypeMetadataUtils.h" 211398a32eSPeter Collingbourne #include "llvm/Bitcode/BitcodeWriter.h" 221398a32eSPeter Collingbourne #include "llvm/IR/Constants.h" 2328ffd326SPeter Collingbourne #include "llvm/IR/DebugInfo.h" 241398a32eSPeter Collingbourne #include "llvm/IR/Intrinsics.h" 251398a32eSPeter Collingbourne #include "llvm/IR/Module.h" 261398a32eSPeter Collingbourne #include "llvm/IR/PassManager.h" 271398a32eSPeter Collingbourne #include "llvm/Pass.h" 280c6a4ff8STeresa Johnson #include "llvm/Support/FileSystem.h" 291398a32eSPeter Collingbourne #include "llvm/Support/ScopedPrinter.h" 300c6a4ff8STeresa Johnson #include "llvm/Support/raw_ostream.h" 310c6a4ff8STeresa Johnson #include "llvm/Transforms/IPO.h" 32002c2d53SPeter Collingbourne #include "llvm/Transforms/IPO/FunctionAttrs.h" 331398a32eSPeter Collingbourne #include "llvm/Transforms/Utils/Cloning.h" 34964f4663SEvgeniy Stepanov #include "llvm/Transforms/Utils/ModuleUtils.h" 351398a32eSPeter Collingbourne using namespace llvm; 361398a32eSPeter Collingbourne 371398a32eSPeter Collingbourne namespace { 381398a32eSPeter Collingbourne 391398a32eSPeter Collingbourne // Promote each local-linkage entity defined by ExportM and used by ImportM by 401398a32eSPeter Collingbourne // changing visibility and appending the given ModuleId. 411398a32eSPeter Collingbourne void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) { 424075ccc7SBob Haarman DenseMap<const Comdat *, Comdat *> RenamedComdats; 436b193966SPeter Collingbourne for (auto &ExportGV : ExportM.global_values()) { 441398a32eSPeter Collingbourne if (!ExportGV.hasLocalLinkage()) 456b193966SPeter Collingbourne continue; 461398a32eSPeter Collingbourne 474075ccc7SBob Haarman auto Name = ExportGV.getName(); 484075ccc7SBob Haarman GlobalValue *ImportGV = ImportM.getNamedValue(Name); 491398a32eSPeter Collingbourne if (!ImportGV || ImportGV->use_empty()) 506b193966SPeter Collingbourne continue; 511398a32eSPeter Collingbourne 524075ccc7SBob Haarman std::string NewName = (Name + ModuleId).str(); 534075ccc7SBob Haarman 544075ccc7SBob Haarman if (const auto *C = ExportGV.getComdat()) 554075ccc7SBob Haarman if (C->getName() == Name) 564075ccc7SBob Haarman RenamedComdats.try_emplace(C, ExportM.getOrInsertComdat(NewName)); 571398a32eSPeter Collingbourne 581398a32eSPeter Collingbourne ExportGV.setName(NewName); 591398a32eSPeter Collingbourne ExportGV.setLinkage(GlobalValue::ExternalLinkage); 601398a32eSPeter Collingbourne ExportGV.setVisibility(GlobalValue::HiddenVisibility); 611398a32eSPeter Collingbourne 621398a32eSPeter Collingbourne ImportGV->setName(NewName); 631398a32eSPeter Collingbourne ImportGV->setVisibility(GlobalValue::HiddenVisibility); 646b193966SPeter Collingbourne } 654075ccc7SBob Haarman 664075ccc7SBob Haarman if (!RenamedComdats.empty()) 674075ccc7SBob Haarman for (auto &GO : ExportM.global_objects()) 684075ccc7SBob Haarman if (auto *C = GO.getComdat()) { 694075ccc7SBob Haarman auto Replacement = RenamedComdats.find(C); 704075ccc7SBob Haarman if (Replacement != RenamedComdats.end()) 714075ccc7SBob Haarman GO.setComdat(Replacement->second); 724075ccc7SBob Haarman } 731398a32eSPeter Collingbourne } 741398a32eSPeter Collingbourne 751398a32eSPeter Collingbourne // Promote all internal (i.e. distinct) type ids used by the module by replacing 761398a32eSPeter Collingbourne // them with external type ids formed using the module id. 771398a32eSPeter Collingbourne // 781398a32eSPeter Collingbourne // Note that this needs to be done before we clone the module because each clone 791398a32eSPeter Collingbourne // will receive its own set of distinct metadata nodes. 801398a32eSPeter Collingbourne void promoteTypeIds(Module &M, StringRef ModuleId) { 811398a32eSPeter Collingbourne DenseMap<Metadata *, Metadata *> LocalToGlobal; 821398a32eSPeter Collingbourne auto ExternalizeTypeId = [&](CallInst *CI, unsigned ArgNo) { 831398a32eSPeter Collingbourne Metadata *MD = 841398a32eSPeter Collingbourne cast<MetadataAsValue>(CI->getArgOperand(ArgNo))->getMetadata(); 851398a32eSPeter Collingbourne 861398a32eSPeter Collingbourne if (isa<MDNode>(MD) && cast<MDNode>(MD)->isDistinct()) { 871398a32eSPeter Collingbourne Metadata *&GlobalMD = LocalToGlobal[MD]; 881398a32eSPeter Collingbourne if (!GlobalMD) { 891398a32eSPeter Collingbourne std::string NewName = 901398a32eSPeter Collingbourne (to_string(LocalToGlobal.size()) + ModuleId).str(); 911398a32eSPeter Collingbourne GlobalMD = MDString::get(M.getContext(), NewName); 921398a32eSPeter Collingbourne } 931398a32eSPeter Collingbourne 941398a32eSPeter Collingbourne CI->setArgOperand(ArgNo, 951398a32eSPeter Collingbourne MetadataAsValue::get(M.getContext(), GlobalMD)); 961398a32eSPeter Collingbourne } 971398a32eSPeter Collingbourne }; 981398a32eSPeter Collingbourne 991398a32eSPeter Collingbourne if (Function *TypeTestFunc = 1001398a32eSPeter Collingbourne M.getFunction(Intrinsic::getName(Intrinsic::type_test))) { 1011398a32eSPeter Collingbourne for (const Use &U : TypeTestFunc->uses()) { 1021398a32eSPeter Collingbourne auto CI = cast<CallInst>(U.getUser()); 1031398a32eSPeter Collingbourne ExternalizeTypeId(CI, 1); 1041398a32eSPeter Collingbourne } 1051398a32eSPeter Collingbourne } 1061398a32eSPeter Collingbourne 1071398a32eSPeter Collingbourne if (Function *TypeCheckedLoadFunc = 1081398a32eSPeter Collingbourne M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load))) { 1091398a32eSPeter Collingbourne for (const Use &U : TypeCheckedLoadFunc->uses()) { 1101398a32eSPeter Collingbourne auto CI = cast<CallInst>(U.getUser()); 1111398a32eSPeter Collingbourne ExternalizeTypeId(CI, 2); 1121398a32eSPeter Collingbourne } 1131398a32eSPeter Collingbourne } 1141398a32eSPeter Collingbourne 1151398a32eSPeter Collingbourne for (GlobalObject &GO : M.global_objects()) { 1161398a32eSPeter Collingbourne SmallVector<MDNode *, 1> MDs; 1171398a32eSPeter Collingbourne GO.getMetadata(LLVMContext::MD_type, MDs); 1181398a32eSPeter Collingbourne 1191398a32eSPeter Collingbourne GO.eraseMetadata(LLVMContext::MD_type); 1201398a32eSPeter Collingbourne for (auto MD : MDs) { 1211398a32eSPeter Collingbourne auto I = LocalToGlobal.find(MD->getOperand(1)); 1221398a32eSPeter Collingbourne if (I == LocalToGlobal.end()) { 1231398a32eSPeter Collingbourne GO.addMetadata(LLVMContext::MD_type, *MD); 1241398a32eSPeter Collingbourne continue; 1251398a32eSPeter Collingbourne } 1261398a32eSPeter Collingbourne GO.addMetadata( 1271398a32eSPeter Collingbourne LLVMContext::MD_type, 1281398a32eSPeter Collingbourne *MDNode::get(M.getContext(), 1291398a32eSPeter Collingbourne ArrayRef<Metadata *>{MD->getOperand(0), I->second})); 1301398a32eSPeter Collingbourne } 1311398a32eSPeter Collingbourne } 1321398a32eSPeter Collingbourne } 1331398a32eSPeter Collingbourne 1341398a32eSPeter Collingbourne // Drop unused globals, and drop type information from function declarations. 1351398a32eSPeter Collingbourne // FIXME: If we made functions typeless then there would be no need to do this. 1361398a32eSPeter Collingbourne void simplifyExternals(Module &M) { 1371398a32eSPeter Collingbourne FunctionType *EmptyFT = 1381398a32eSPeter Collingbourne FunctionType::get(Type::getVoidTy(M.getContext()), false); 1391398a32eSPeter Collingbourne 1401398a32eSPeter Collingbourne for (auto I = M.begin(), E = M.end(); I != E;) { 1411398a32eSPeter Collingbourne Function &F = *I++; 1421398a32eSPeter Collingbourne if (F.isDeclaration() && F.use_empty()) { 1431398a32eSPeter Collingbourne F.eraseFromParent(); 1441398a32eSPeter Collingbourne continue; 1451398a32eSPeter Collingbourne } 1461398a32eSPeter Collingbourne 1471398a32eSPeter Collingbourne if (!F.isDeclaration() || F.getFunctionType() == EmptyFT) 1481398a32eSPeter Collingbourne continue; 1491398a32eSPeter Collingbourne 1501398a32eSPeter Collingbourne Function *NewF = 1511398a32eSPeter Collingbourne Function::Create(EmptyFT, GlobalValue::ExternalLinkage, "", &M); 1521398a32eSPeter Collingbourne NewF->setVisibility(F.getVisibility()); 1531398a32eSPeter Collingbourne NewF->takeName(&F); 1541398a32eSPeter Collingbourne F.replaceAllUsesWith(ConstantExpr::getBitCast(NewF, F.getType())); 1551398a32eSPeter Collingbourne F.eraseFromParent(); 1561398a32eSPeter Collingbourne } 1571398a32eSPeter Collingbourne 1581398a32eSPeter Collingbourne for (auto I = M.global_begin(), E = M.global_end(); I != E;) { 1591398a32eSPeter Collingbourne GlobalVariable &GV = *I++; 1601398a32eSPeter Collingbourne if (GV.isDeclaration() && GV.use_empty()) { 1611398a32eSPeter Collingbourne GV.eraseFromParent(); 1621398a32eSPeter Collingbourne continue; 1631398a32eSPeter Collingbourne } 1641398a32eSPeter Collingbourne } 1651398a32eSPeter Collingbourne } 1661398a32eSPeter Collingbourne 1671398a32eSPeter Collingbourne void filterModule( 168061f4a5fSBenjamin Kramer Module *M, function_ref<bool(const GlobalValue *)> ShouldKeepDefinition) { 1696de81347SBob Haarman for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end(); 1706de81347SBob Haarman I != E;) { 1716de81347SBob Haarman GlobalAlias *GA = &*I++; 1726de81347SBob Haarman if (ShouldKeepDefinition(GA)) 1736de81347SBob Haarman continue; 1746de81347SBob Haarman 1756de81347SBob Haarman GlobalObject *GO; 1766de81347SBob Haarman if (GA->getValueType()->isFunctionTy()) 1776de81347SBob Haarman GO = Function::Create(cast<FunctionType>(GA->getValueType()), 1786de81347SBob Haarman GlobalValue::ExternalLinkage, "", M); 1796de81347SBob Haarman else 1806de81347SBob Haarman GO = new GlobalVariable( 1816de81347SBob Haarman *M, GA->getValueType(), false, GlobalValue::ExternalLinkage, 182*f4dc59baSSerge Guelton nullptr, "", nullptr, 1836de81347SBob Haarman GA->getThreadLocalMode(), GA->getType()->getAddressSpace()); 1846de81347SBob Haarman GO->takeName(GA); 1856de81347SBob Haarman GA->replaceAllUsesWith(GO); 1866de81347SBob Haarman GA->eraseFromParent(); 1876de81347SBob Haarman } 1886de81347SBob Haarman 1891398a32eSPeter Collingbourne for (Function &F : *M) { 1901398a32eSPeter Collingbourne if (ShouldKeepDefinition(&F)) 1911398a32eSPeter Collingbourne continue; 1921398a32eSPeter Collingbourne 1931398a32eSPeter Collingbourne F.deleteBody(); 19420a00933SPeter Collingbourne F.setComdat(nullptr); 1951398a32eSPeter Collingbourne F.clearMetadata(); 1961398a32eSPeter Collingbourne } 1971398a32eSPeter Collingbourne 1981398a32eSPeter Collingbourne for (GlobalVariable &GV : M->globals()) { 1991398a32eSPeter Collingbourne if (ShouldKeepDefinition(&GV)) 2001398a32eSPeter Collingbourne continue; 2011398a32eSPeter Collingbourne 2021398a32eSPeter Collingbourne GV.setInitializer(nullptr); 2031398a32eSPeter Collingbourne GV.setLinkage(GlobalValue::ExternalLinkage); 20420a00933SPeter Collingbourne GV.setComdat(nullptr); 2051398a32eSPeter Collingbourne GV.clearMetadata(); 2061398a32eSPeter Collingbourne } 2071398a32eSPeter Collingbourne } 2081398a32eSPeter Collingbourne 209002c2d53SPeter Collingbourne void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) { 210002c2d53SPeter Collingbourne if (auto *F = dyn_cast<Function>(C)) 211002c2d53SPeter Collingbourne return Fn(F); 2123baa72afSPeter Collingbourne if (isa<GlobalValue>(C)) 2133baa72afSPeter Collingbourne return; 214002c2d53SPeter Collingbourne for (Value *Op : C->operands()) 215002c2d53SPeter Collingbourne forEachVirtualFunction(cast<Constant>(Op), Fn); 216002c2d53SPeter Collingbourne } 217002c2d53SPeter Collingbourne 2181398a32eSPeter Collingbourne // If it's possible to split M into regular and thin LTO parts, do so and write 2191398a32eSPeter Collingbourne // a multi-module bitcode file with the two parts to OS. Otherwise, write only a 2201398a32eSPeter Collingbourne // regular LTO bitcode file to OS. 221002c2d53SPeter Collingbourne void splitAndWriteThinLTOBitcode( 2220c6a4ff8STeresa Johnson raw_ostream &OS, raw_ostream *ThinLinkOS, 2230c6a4ff8STeresa Johnson function_ref<AAResults &(Function &)> AARGetter, Module &M) { 224964f4663SEvgeniy Stepanov std::string ModuleId = getUniqueModuleId(&M); 2251398a32eSPeter Collingbourne if (ModuleId.empty()) { 2261398a32eSPeter Collingbourne // We couldn't generate a module ID for this module, just write it out as a 2271398a32eSPeter Collingbourne // regular LTO module. 2281398a32eSPeter Collingbourne WriteBitcodeToFile(&M, OS); 2290c6a4ff8STeresa Johnson if (ThinLinkOS) 2300c6a4ff8STeresa Johnson // We don't have a ThinLTO part, but still write the module to the 2310c6a4ff8STeresa Johnson // ThinLinkOS if requested so that the expected output file is produced. 2320c6a4ff8STeresa Johnson WriteBitcodeToFile(&M, *ThinLinkOS); 2331398a32eSPeter Collingbourne return; 2341398a32eSPeter Collingbourne } 2351398a32eSPeter Collingbourne 2361398a32eSPeter Collingbourne promoteTypeIds(M, ModuleId); 2371398a32eSPeter Collingbourne 238002c2d53SPeter Collingbourne // Returns whether a global has attached type metadata. Such globals may 239002c2d53SPeter Collingbourne // participate in CFI or whole-program devirtualization, so they need to 240002c2d53SPeter Collingbourne // appear in the merged module instead of the thin LTO module. 241002c2d53SPeter Collingbourne auto HasTypeMetadata = [&](const GlobalObject *GO) { 2421398a32eSPeter Collingbourne SmallVector<MDNode *, 1> MDs; 243002c2d53SPeter Collingbourne GO->getMetadata(LLVMContext::MD_type, MDs); 2441398a32eSPeter Collingbourne return !MDs.empty(); 2451398a32eSPeter Collingbourne }; 2461398a32eSPeter Collingbourne 247002c2d53SPeter Collingbourne // Collect the set of virtual functions that are eligible for virtual constant 248002c2d53SPeter Collingbourne // propagation. Each eligible function must not access memory, must return 249002c2d53SPeter Collingbourne // an integer of width <=64 bits, must take at least one argument, must not 250002c2d53SPeter Collingbourne // use its first argument (assumed to be "this") and all arguments other than 251002c2d53SPeter Collingbourne // the first one must be of <=64 bit integer type. 252002c2d53SPeter Collingbourne // 253002c2d53SPeter Collingbourne // Note that we test whether this copy of the function is readnone, rather 254002c2d53SPeter Collingbourne // than testing function attributes, which must hold for any copy of the 255002c2d53SPeter Collingbourne // function, even a less optimized version substituted at link time. This is 256002c2d53SPeter Collingbourne // sound because the virtual constant propagation optimizations effectively 257002c2d53SPeter Collingbourne // inline all implementations of the virtual function into each call site, 258002c2d53SPeter Collingbourne // rather than using function attributes to perform local optimization. 259002c2d53SPeter Collingbourne std::set<const Function *> EligibleVirtualFns; 2604075ccc7SBob Haarman // If any member of a comdat lives in MergedM, put all members of that 2614075ccc7SBob Haarman // comdat in MergedM to keep the comdat together. 2624075ccc7SBob Haarman DenseSet<const Comdat *> MergedMComdats; 263002c2d53SPeter Collingbourne for (GlobalVariable &GV : M.globals()) 2644075ccc7SBob Haarman if (HasTypeMetadata(&GV)) { 2654075ccc7SBob Haarman if (const auto *C = GV.getComdat()) 2664075ccc7SBob Haarman MergedMComdats.insert(C); 267002c2d53SPeter Collingbourne forEachVirtualFunction(GV.getInitializer(), [&](Function *F) { 268002c2d53SPeter Collingbourne auto *RT = dyn_cast<IntegerType>(F->getReturnType()); 269002c2d53SPeter Collingbourne if (!RT || RT->getBitWidth() > 64 || F->arg_empty() || 270002c2d53SPeter Collingbourne !F->arg_begin()->use_empty()) 271002c2d53SPeter Collingbourne return; 272002c2d53SPeter Collingbourne for (auto &Arg : make_range(std::next(F->arg_begin()), F->arg_end())) { 273002c2d53SPeter Collingbourne auto *ArgT = dyn_cast<IntegerType>(Arg.getType()); 274002c2d53SPeter Collingbourne if (!ArgT || ArgT->getBitWidth() > 64) 275002c2d53SPeter Collingbourne return; 276002c2d53SPeter Collingbourne } 277002c2d53SPeter Collingbourne if (computeFunctionBodyMemoryAccess(*F, AARGetter(*F)) == MAK_ReadNone) 278002c2d53SPeter Collingbourne EligibleVirtualFns.insert(F); 279002c2d53SPeter Collingbourne }); 2804075ccc7SBob Haarman } 281002c2d53SPeter Collingbourne 2821398a32eSPeter Collingbourne ValueToValueMapTy VMap; 283002c2d53SPeter Collingbourne std::unique_ptr<Module> MergedM( 284002c2d53SPeter Collingbourne CloneModule(&M, VMap, [&](const GlobalValue *GV) -> bool { 2854075ccc7SBob Haarman if (const auto *C = GV->getComdat()) 2864075ccc7SBob Haarman if (MergedMComdats.count(C)) 2874075ccc7SBob Haarman return true; 288002c2d53SPeter Collingbourne if (auto *F = dyn_cast<Function>(GV)) 289002c2d53SPeter Collingbourne return EligibleVirtualFns.count(F); 290002c2d53SPeter Collingbourne if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV->getBaseObject())) 291002c2d53SPeter Collingbourne return HasTypeMetadata(GVar); 292002c2d53SPeter Collingbourne return false; 293002c2d53SPeter Collingbourne })); 29428ffd326SPeter Collingbourne StripDebugInfo(*MergedM); 2951398a32eSPeter Collingbourne 296002c2d53SPeter Collingbourne for (Function &F : *MergedM) 297002c2d53SPeter Collingbourne if (!F.isDeclaration()) { 298002c2d53SPeter Collingbourne // Reset the linkage of all functions eligible for virtual constant 299002c2d53SPeter Collingbourne // propagation. The canonical definitions live in the thin LTO module so 300002c2d53SPeter Collingbourne // that they can be imported. 301002c2d53SPeter Collingbourne F.setLinkage(GlobalValue::AvailableExternallyLinkage); 302002c2d53SPeter Collingbourne F.setComdat(nullptr); 303002c2d53SPeter Collingbourne } 304002c2d53SPeter Collingbourne 3054075ccc7SBob Haarman // Remove all globals with type metadata, globals with comdats that live in 3064075ccc7SBob Haarman // MergedM, and aliases pointing to such globals from the thin LTO module. 307002c2d53SPeter Collingbourne filterModule(&M, [&](const GlobalValue *GV) { 308002c2d53SPeter Collingbourne if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV->getBaseObject())) 3094075ccc7SBob Haarman if (HasTypeMetadata(GVar)) 3104075ccc7SBob Haarman return false; 3114075ccc7SBob Haarman if (const auto *C = GV->getComdat()) 3124075ccc7SBob Haarman if (MergedMComdats.count(C)) 3134075ccc7SBob Haarman return false; 314002c2d53SPeter Collingbourne return true; 315002c2d53SPeter Collingbourne }); 3161398a32eSPeter Collingbourne 3171398a32eSPeter Collingbourne promoteInternals(*MergedM, M, ModuleId); 3181398a32eSPeter Collingbourne promoteInternals(M, *MergedM, ModuleId); 3191398a32eSPeter Collingbourne 3201398a32eSPeter Collingbourne simplifyExternals(*MergedM); 3211398a32eSPeter Collingbourne 3221398a32eSPeter Collingbourne 3231398a32eSPeter Collingbourne // FIXME: Try to re-use BSI and PFI from the original module here. 32494624acaSTeresa Johnson ProfileSummaryInfo PSI(M); 32594624acaSTeresa Johnson ModuleSummaryIndex Index = buildModuleSummaryIndex(M, nullptr, &PSI); 3260c6a4ff8STeresa Johnson 3270c6a4ff8STeresa Johnson SmallVector<char, 0> Buffer; 3280c6a4ff8STeresa Johnson 3290c6a4ff8STeresa Johnson BitcodeWriter W(Buffer); 3300c6a4ff8STeresa Johnson // Save the module hash produced for the full bitcode, which will 3310c6a4ff8STeresa Johnson // be used in the backends, and use that in the minimized bitcode 3320c6a4ff8STeresa Johnson // produced for the full link. 3330c6a4ff8STeresa Johnson ModuleHash ModHash = {{0}}; 3341398a32eSPeter Collingbourne W.writeModule(&M, /*ShouldPreserveUseListOrder=*/false, &Index, 3350c6a4ff8STeresa Johnson /*GenerateHash=*/true, &ModHash); 3361398a32eSPeter Collingbourne W.writeModule(MergedM.get()); 337a0f371a1SPeter Collingbourne W.writeStrtab(); 3381398a32eSPeter Collingbourne OS << Buffer; 3390c6a4ff8STeresa Johnson 3400c6a4ff8STeresa Johnson // If a minimized bitcode module was requested for the thin link, 3410c6a4ff8STeresa Johnson // strip the debug info (the merged module was already stripped above) 3420c6a4ff8STeresa Johnson // and write it to the given OS. 3430c6a4ff8STeresa Johnson if (ThinLinkOS) { 3440c6a4ff8STeresa Johnson Buffer.clear(); 3450c6a4ff8STeresa Johnson BitcodeWriter W2(Buffer); 3460c6a4ff8STeresa Johnson StripDebugInfo(M); 3470c6a4ff8STeresa Johnson W2.writeModule(&M, /*ShouldPreserveUseListOrder=*/false, &Index, 3480c6a4ff8STeresa Johnson /*GenerateHash=*/false, &ModHash); 3490c6a4ff8STeresa Johnson W2.writeModule(MergedM.get()); 350a0f371a1SPeter Collingbourne W2.writeStrtab(); 3510c6a4ff8STeresa Johnson *ThinLinkOS << Buffer; 3520c6a4ff8STeresa Johnson } 3531398a32eSPeter Collingbourne } 3541398a32eSPeter Collingbourne 3551398a32eSPeter Collingbourne // Returns whether this module needs to be split because it uses type metadata. 3561398a32eSPeter Collingbourne bool requiresSplit(Module &M) { 3571398a32eSPeter Collingbourne SmallVector<MDNode *, 1> MDs; 3581398a32eSPeter Collingbourne for (auto &GO : M.global_objects()) { 3591398a32eSPeter Collingbourne GO.getMetadata(LLVMContext::MD_type, MDs); 3601398a32eSPeter Collingbourne if (!MDs.empty()) 3611398a32eSPeter Collingbourne return true; 3621398a32eSPeter Collingbourne } 3631398a32eSPeter Collingbourne 3641398a32eSPeter Collingbourne return false; 3651398a32eSPeter Collingbourne } 3661398a32eSPeter Collingbourne 3670c6a4ff8STeresa Johnson void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS, 368002c2d53SPeter Collingbourne function_ref<AAResults &(Function &)> AARGetter, 369002c2d53SPeter Collingbourne Module &M, const ModuleSummaryIndex *Index) { 3701398a32eSPeter Collingbourne // See if this module has any type metadata. If so, we need to split it. 3711398a32eSPeter Collingbourne if (requiresSplit(M)) 3720c6a4ff8STeresa Johnson return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M); 3731398a32eSPeter Collingbourne 3741398a32eSPeter Collingbourne // Otherwise we can just write it out as a regular module. 3750c6a4ff8STeresa Johnson 3760c6a4ff8STeresa Johnson // Save the module hash produced for the full bitcode, which will 3770c6a4ff8STeresa Johnson // be used in the backends, and use that in the minimized bitcode 3780c6a4ff8STeresa Johnson // produced for the full link. 3790c6a4ff8STeresa Johnson ModuleHash ModHash = {{0}}; 3801398a32eSPeter Collingbourne WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false, Index, 3810c6a4ff8STeresa Johnson /*GenerateHash=*/true, &ModHash); 3820c6a4ff8STeresa Johnson // If a minimized bitcode module was requested for the thin link, 3830c6a4ff8STeresa Johnson // strip the debug info and write it to the given OS. 3840c6a4ff8STeresa Johnson if (ThinLinkOS) { 3850c6a4ff8STeresa Johnson StripDebugInfo(M); 3860c6a4ff8STeresa Johnson WriteBitcodeToFile(&M, *ThinLinkOS, /*ShouldPreserveUseListOrder=*/false, 3870c6a4ff8STeresa Johnson Index, 3880c6a4ff8STeresa Johnson /*GenerateHash=*/false, &ModHash); 3890c6a4ff8STeresa Johnson } 3901398a32eSPeter Collingbourne } 3911398a32eSPeter Collingbourne 3921398a32eSPeter Collingbourne class WriteThinLTOBitcode : public ModulePass { 3931398a32eSPeter Collingbourne raw_ostream &OS; // raw_ostream to print on 3940c6a4ff8STeresa Johnson // The output stream on which to emit a minimized module for use 3950c6a4ff8STeresa Johnson // just in the thin link, if requested. 3960c6a4ff8STeresa Johnson raw_ostream *ThinLinkOS; 3971398a32eSPeter Collingbourne 3981398a32eSPeter Collingbourne public: 3991398a32eSPeter Collingbourne static char ID; // Pass identification, replacement for typeid 4000c6a4ff8STeresa Johnson WriteThinLTOBitcode() : ModulePass(ID), OS(dbgs()), ThinLinkOS(nullptr) { 4011398a32eSPeter Collingbourne initializeWriteThinLTOBitcodePass(*PassRegistry::getPassRegistry()); 4021398a32eSPeter Collingbourne } 4031398a32eSPeter Collingbourne 4040c6a4ff8STeresa Johnson explicit WriteThinLTOBitcode(raw_ostream &o, raw_ostream *ThinLinkOS) 4050c6a4ff8STeresa Johnson : ModulePass(ID), OS(o), ThinLinkOS(ThinLinkOS) { 4061398a32eSPeter Collingbourne initializeWriteThinLTOBitcodePass(*PassRegistry::getPassRegistry()); 4071398a32eSPeter Collingbourne } 4081398a32eSPeter Collingbourne 4091398a32eSPeter Collingbourne StringRef getPassName() const override { return "ThinLTO Bitcode Writer"; } 4101398a32eSPeter Collingbourne 4111398a32eSPeter Collingbourne bool runOnModule(Module &M) override { 4121398a32eSPeter Collingbourne const ModuleSummaryIndex *Index = 4131398a32eSPeter Collingbourne &(getAnalysis<ModuleSummaryIndexWrapperPass>().getIndex()); 4140c6a4ff8STeresa Johnson writeThinLTOBitcode(OS, ThinLinkOS, LegacyAARGetter(*this), M, Index); 4151398a32eSPeter Collingbourne return true; 4161398a32eSPeter Collingbourne } 4171398a32eSPeter Collingbourne void getAnalysisUsage(AnalysisUsage &AU) const override { 4181398a32eSPeter Collingbourne AU.setPreservesAll(); 419002c2d53SPeter Collingbourne AU.addRequired<AssumptionCacheTracker>(); 4201398a32eSPeter Collingbourne AU.addRequired<ModuleSummaryIndexWrapperPass>(); 421002c2d53SPeter Collingbourne AU.addRequired<TargetLibraryInfoWrapperPass>(); 4221398a32eSPeter Collingbourne } 4231398a32eSPeter Collingbourne }; 4241398a32eSPeter Collingbourne } // anonymous namespace 4251398a32eSPeter Collingbourne 4261398a32eSPeter Collingbourne char WriteThinLTOBitcode::ID = 0; 4271398a32eSPeter Collingbourne INITIALIZE_PASS_BEGIN(WriteThinLTOBitcode, "write-thinlto-bitcode", 4281398a32eSPeter Collingbourne "Write ThinLTO Bitcode", false, true) 429002c2d53SPeter Collingbourne INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) 4301398a32eSPeter Collingbourne INITIALIZE_PASS_DEPENDENCY(ModuleSummaryIndexWrapperPass) 431002c2d53SPeter Collingbourne INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 4321398a32eSPeter Collingbourne INITIALIZE_PASS_END(WriteThinLTOBitcode, "write-thinlto-bitcode", 4331398a32eSPeter Collingbourne "Write ThinLTO Bitcode", false, true) 4341398a32eSPeter Collingbourne 4350c6a4ff8STeresa Johnson ModulePass *llvm::createWriteThinLTOBitcodePass(raw_ostream &Str, 4360c6a4ff8STeresa Johnson raw_ostream *ThinLinkOS) { 4370c6a4ff8STeresa Johnson return new WriteThinLTOBitcode(Str, ThinLinkOS); 4381398a32eSPeter Collingbourne } 439