11398a32eSPeter Collingbourne //===- ThinLTOBitcodeWriter.cpp - Bitcode writing pass for ThinLTO --------===//
21398a32eSPeter Collingbourne //
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
61398a32eSPeter Collingbourne //
71398a32eSPeter Collingbourne //===----------------------------------------------------------------------===//
81398a32eSPeter Collingbourne 
96b411418STim Shen #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
10002c2d53SPeter Collingbourne #include "llvm/Analysis/BasicAliasAnalysis.h"
111398a32eSPeter Collingbourne #include "llvm/Analysis/ModuleSummaryAnalysis.h"
1294624acaSTeresa Johnson #include "llvm/Analysis/ProfileSummaryInfo.h"
131398a32eSPeter Collingbourne #include "llvm/Analysis/TypeMetadataUtils.h"
141398a32eSPeter Collingbourne #include "llvm/Bitcode/BitcodeWriter.h"
151398a32eSPeter Collingbourne #include "llvm/IR/Constants.h"
1628ffd326SPeter Collingbourne #include "llvm/IR/DebugInfo.h"
171398a32eSPeter Collingbourne #include "llvm/IR/Intrinsics.h"
181398a32eSPeter Collingbourne #include "llvm/IR/Module.h"
191398a32eSPeter Collingbourne #include "llvm/IR/PassManager.h"
20230b2567SVlad Tsyrklevich #include "llvm/Object/ModuleSymbolTable.h"
211398a32eSPeter Collingbourne #include "llvm/Pass.h"
221398a32eSPeter Collingbourne #include "llvm/Support/ScopedPrinter.h"
230c6a4ff8STeresa Johnson #include "llvm/Support/raw_ostream.h"
240c6a4ff8STeresa Johnson #include "llvm/Transforms/IPO.h"
25002c2d53SPeter Collingbourne #include "llvm/Transforms/IPO/FunctionAttrs.h"
26d3704f67SGeorge Rimar #include "llvm/Transforms/IPO/FunctionImport.h"
270e497d15SPeter Collingbourne #include "llvm/Transforms/IPO/LowerTypeTests.h"
281398a32eSPeter Collingbourne #include "llvm/Transforms/Utils/Cloning.h"
29964f4663SEvgeniy Stepanov #include "llvm/Transforms/Utils/ModuleUtils.h"
301398a32eSPeter Collingbourne using namespace llvm;
311398a32eSPeter Collingbourne 
321398a32eSPeter Collingbourne namespace {
331398a32eSPeter Collingbourne 
341398a32eSPeter Collingbourne // Promote each local-linkage entity defined by ExportM and used by ImportM by
351398a32eSPeter Collingbourne // changing visibility and appending the given ModuleId.
364d4ee93dSEvgeniy Stepanov void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
374d4ee93dSEvgeniy Stepanov                       SetVector<GlobalValue *> &PromoteExtra) {
384075ccc7SBob Haarman   DenseMap<const Comdat *, Comdat *> RenamedComdats;
396b193966SPeter Collingbourne   for (auto &ExportGV : ExportM.global_values()) {
401398a32eSPeter Collingbourne     if (!ExportGV.hasLocalLinkage())
416b193966SPeter Collingbourne       continue;
421398a32eSPeter Collingbourne 
434075ccc7SBob Haarman     auto Name = ExportGV.getName();
441f034226SPeter Collingbourne     GlobalValue *ImportGV = nullptr;
451f034226SPeter Collingbourne     if (!PromoteExtra.count(&ExportGV)) {
461f034226SPeter Collingbourne       ImportGV = ImportM.getNamedValue(Name);
471f034226SPeter Collingbourne       if (!ImportGV)
486b193966SPeter Collingbourne         continue;
491f034226SPeter Collingbourne       ImportGV->removeDeadConstantUsers();
501f034226SPeter Collingbourne       if (ImportGV->use_empty()) {
511f034226SPeter Collingbourne         ImportGV->eraseFromParent();
521f034226SPeter Collingbourne         continue;
531f034226SPeter Collingbourne       }
541f034226SPeter Collingbourne     }
551398a32eSPeter Collingbourne 
564075ccc7SBob Haarman     std::string NewName = (Name + ModuleId).str();
574075ccc7SBob Haarman 
584075ccc7SBob Haarman     if (const auto *C = ExportGV.getComdat())
594075ccc7SBob Haarman       if (C->getName() == Name)
604075ccc7SBob Haarman         RenamedComdats.try_emplace(C, ExportM.getOrInsertComdat(NewName));
611398a32eSPeter Collingbourne 
621398a32eSPeter Collingbourne     ExportGV.setName(NewName);
631398a32eSPeter Collingbourne     ExportGV.setLinkage(GlobalValue::ExternalLinkage);
641398a32eSPeter Collingbourne     ExportGV.setVisibility(GlobalValue::HiddenVisibility);
651398a32eSPeter Collingbourne 
664d4ee93dSEvgeniy Stepanov     if (ImportGV) {
671398a32eSPeter Collingbourne       ImportGV->setName(NewName);
681398a32eSPeter Collingbourne       ImportGV->setVisibility(GlobalValue::HiddenVisibility);
696b193966SPeter Collingbourne     }
704d4ee93dSEvgeniy Stepanov   }
714075ccc7SBob Haarman 
724075ccc7SBob Haarman   if (!RenamedComdats.empty())
734075ccc7SBob Haarman     for (auto &GO : ExportM.global_objects())
744075ccc7SBob Haarman       if (auto *C = GO.getComdat()) {
754075ccc7SBob Haarman         auto Replacement = RenamedComdats.find(C);
764075ccc7SBob Haarman         if (Replacement != RenamedComdats.end())
774075ccc7SBob Haarman           GO.setComdat(Replacement->second);
784075ccc7SBob Haarman       }
791398a32eSPeter Collingbourne }
801398a32eSPeter Collingbourne 
811398a32eSPeter Collingbourne // Promote all internal (i.e. distinct) type ids used by the module by replacing
821398a32eSPeter Collingbourne // them with external type ids formed using the module id.
831398a32eSPeter Collingbourne //
841398a32eSPeter Collingbourne // Note that this needs to be done before we clone the module because each clone
851398a32eSPeter Collingbourne // will receive its own set of distinct metadata nodes.
861398a32eSPeter Collingbourne void promoteTypeIds(Module &M, StringRef ModuleId) {
871398a32eSPeter Collingbourne   DenseMap<Metadata *, Metadata *> LocalToGlobal;
881398a32eSPeter Collingbourne   auto ExternalizeTypeId = [&](CallInst *CI, unsigned ArgNo) {
891398a32eSPeter Collingbourne     Metadata *MD =
901398a32eSPeter Collingbourne         cast<MetadataAsValue>(CI->getArgOperand(ArgNo))->getMetadata();
911398a32eSPeter Collingbourne 
921398a32eSPeter Collingbourne     if (isa<MDNode>(MD) && cast<MDNode>(MD)->isDistinct()) {
931398a32eSPeter Collingbourne       Metadata *&GlobalMD = LocalToGlobal[MD];
941398a32eSPeter Collingbourne       if (!GlobalMD) {
953a13ed60SBenjamin Kramer         std::string NewName = (Twine(LocalToGlobal.size()) + ModuleId).str();
961398a32eSPeter Collingbourne         GlobalMD = MDString::get(M.getContext(), NewName);
971398a32eSPeter Collingbourne       }
981398a32eSPeter Collingbourne 
991398a32eSPeter Collingbourne       CI->setArgOperand(ArgNo,
1001398a32eSPeter Collingbourne                         MetadataAsValue::get(M.getContext(), GlobalMD));
1011398a32eSPeter Collingbourne     }
1021398a32eSPeter Collingbourne   };
1031398a32eSPeter Collingbourne 
1041398a32eSPeter Collingbourne   if (Function *TypeTestFunc =
1051398a32eSPeter Collingbourne           M.getFunction(Intrinsic::getName(Intrinsic::type_test))) {
1061398a32eSPeter Collingbourne     for (const Use &U : TypeTestFunc->uses()) {
1071398a32eSPeter Collingbourne       auto CI = cast<CallInst>(U.getUser());
1081398a32eSPeter Collingbourne       ExternalizeTypeId(CI, 1);
1091398a32eSPeter Collingbourne     }
1101398a32eSPeter Collingbourne   }
1111398a32eSPeter Collingbourne 
1121398a32eSPeter Collingbourne   if (Function *TypeCheckedLoadFunc =
1131398a32eSPeter Collingbourne           M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load))) {
1141398a32eSPeter Collingbourne     for (const Use &U : TypeCheckedLoadFunc->uses()) {
1151398a32eSPeter Collingbourne       auto CI = cast<CallInst>(U.getUser());
1161398a32eSPeter Collingbourne       ExternalizeTypeId(CI, 2);
1171398a32eSPeter Collingbourne     }
1181398a32eSPeter Collingbourne   }
1191398a32eSPeter Collingbourne 
1201398a32eSPeter Collingbourne   for (GlobalObject &GO : M.global_objects()) {
1211398a32eSPeter Collingbourne     SmallVector<MDNode *, 1> MDs;
1221398a32eSPeter Collingbourne     GO.getMetadata(LLVMContext::MD_type, MDs);
1231398a32eSPeter Collingbourne 
1241398a32eSPeter Collingbourne     GO.eraseMetadata(LLVMContext::MD_type);
1251398a32eSPeter Collingbourne     for (auto MD : MDs) {
1261398a32eSPeter Collingbourne       auto I = LocalToGlobal.find(MD->getOperand(1));
1271398a32eSPeter Collingbourne       if (I == LocalToGlobal.end()) {
1281398a32eSPeter Collingbourne         GO.addMetadata(LLVMContext::MD_type, *MD);
1291398a32eSPeter Collingbourne         continue;
1301398a32eSPeter Collingbourne       }
1311398a32eSPeter Collingbourne       GO.addMetadata(
1321398a32eSPeter Collingbourne           LLVMContext::MD_type,
1330deb9a9aSBenjamin Kramer           *MDNode::get(M.getContext(), {MD->getOperand(0), I->second}));
1341398a32eSPeter Collingbourne     }
1351398a32eSPeter Collingbourne   }
1361398a32eSPeter Collingbourne }
1371398a32eSPeter Collingbourne 
1381398a32eSPeter Collingbourne // Drop unused globals, and drop type information from function declarations.
1391398a32eSPeter Collingbourne // FIXME: If we made functions typeless then there would be no need to do this.
1401398a32eSPeter Collingbourne void simplifyExternals(Module &M) {
1411398a32eSPeter Collingbourne   FunctionType *EmptyFT =
1421398a32eSPeter Collingbourne       FunctionType::get(Type::getVoidTy(M.getContext()), false);
1431398a32eSPeter Collingbourne 
1441398a32eSPeter Collingbourne   for (auto I = M.begin(), E = M.end(); I != E;) {
1451398a32eSPeter Collingbourne     Function &F = *I++;
1461398a32eSPeter Collingbourne     if (F.isDeclaration() && F.use_empty()) {
1471398a32eSPeter Collingbourne       F.eraseFromParent();
1481398a32eSPeter Collingbourne       continue;
1491398a32eSPeter Collingbourne     }
1501398a32eSPeter Collingbourne 
15193fdaca5SPeter Collingbourne     if (!F.isDeclaration() || F.getFunctionType() == EmptyFT ||
15293fdaca5SPeter Collingbourne         // Changing the type of an intrinsic may invalidate the IR.
15393fdaca5SPeter Collingbourne         F.getName().startswith("llvm."))
1541398a32eSPeter Collingbourne       continue;
1551398a32eSPeter Collingbourne 
1561398a32eSPeter Collingbourne     Function *NewF =
157f920da00SDylan McKay         Function::Create(EmptyFT, GlobalValue::ExternalLinkage,
158f920da00SDylan McKay                          F.getAddressSpace(), "", &M);
1591398a32eSPeter Collingbourne     NewF->setVisibility(F.getVisibility());
1601398a32eSPeter Collingbourne     NewF->takeName(&F);
1611398a32eSPeter Collingbourne     F.replaceAllUsesWith(ConstantExpr::getBitCast(NewF, F.getType()));
1621398a32eSPeter Collingbourne     F.eraseFromParent();
1631398a32eSPeter Collingbourne   }
1641398a32eSPeter Collingbourne 
1651398a32eSPeter Collingbourne   for (auto I = M.global_begin(), E = M.global_end(); I != E;) {
1661398a32eSPeter Collingbourne     GlobalVariable &GV = *I++;
1671398a32eSPeter Collingbourne     if (GV.isDeclaration() && GV.use_empty()) {
1681398a32eSPeter Collingbourne       GV.eraseFromParent();
1691398a32eSPeter Collingbourne       continue;
1701398a32eSPeter Collingbourne     }
1711398a32eSPeter Collingbourne   }
1721398a32eSPeter Collingbourne }
1731398a32eSPeter Collingbourne 
174d3704f67SGeorge Rimar static void
175d3704f67SGeorge Rimar filterModule(Module *M,
176d3704f67SGeorge Rimar              function_ref<bool(const GlobalValue *)> ShouldKeepDefinition) {
177d3704f67SGeorge Rimar   std::vector<GlobalValue *> V;
178d3704f67SGeorge Rimar   for (GlobalValue &GV : M->global_values())
179d3704f67SGeorge Rimar     if (!ShouldKeepDefinition(&GV))
180d3704f67SGeorge Rimar       V.push_back(&GV);
18154565249SGeorge Rimar 
182d3704f67SGeorge Rimar   for (GlobalValue *GV : V)
183d3704f67SGeorge Rimar     if (!convertToDeclaration(*GV))
184d3704f67SGeorge Rimar       GV->eraseFromParent();
1851398a32eSPeter Collingbourne }
1861398a32eSPeter Collingbourne 
187002c2d53SPeter Collingbourne void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) {
188002c2d53SPeter Collingbourne   if (auto *F = dyn_cast<Function>(C))
189002c2d53SPeter Collingbourne     return Fn(F);
1903baa72afSPeter Collingbourne   if (isa<GlobalValue>(C))
1913baa72afSPeter Collingbourne     return;
192002c2d53SPeter Collingbourne   for (Value *Op : C->operands())
193002c2d53SPeter Collingbourne     forEachVirtualFunction(cast<Constant>(Op), Fn);
194002c2d53SPeter Collingbourne }
195002c2d53SPeter Collingbourne 
1961398a32eSPeter Collingbourne // If it's possible to split M into regular and thin LTO parts, do so and write
1971398a32eSPeter Collingbourne // a multi-module bitcode file with the two parts to OS. Otherwise, write only a
1981398a32eSPeter Collingbourne // regular LTO bitcode file to OS.
199002c2d53SPeter Collingbourne void splitAndWriteThinLTOBitcode(
2000c6a4ff8STeresa Johnson     raw_ostream &OS, raw_ostream *ThinLinkOS,
2010c6a4ff8STeresa Johnson     function_ref<AAResults &(Function &)> AARGetter, Module &M) {
202964f4663SEvgeniy Stepanov   std::string ModuleId = getUniqueModuleId(&M);
2031398a32eSPeter Collingbourne   if (ModuleId.empty()) {
2046867ab7cSVlad Tsyrklevich     // We couldn't generate a module ID for this module, write it out as a
2056867ab7cSVlad Tsyrklevich     // regular LTO module with an index for summary-based dead stripping.
2066867ab7cSVlad Tsyrklevich     ProfileSummaryInfo PSI(M);
2076867ab7cSVlad Tsyrklevich     M.addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
2086867ab7cSVlad Tsyrklevich     ModuleSummaryIndex Index = buildModuleSummaryIndex(M, nullptr, &PSI);
2096867ab7cSVlad Tsyrklevich     WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false, &Index);
2106867ab7cSVlad Tsyrklevich 
2110c6a4ff8STeresa Johnson     if (ThinLinkOS)
2120c6a4ff8STeresa Johnson       // We don't have a ThinLTO part, but still write the module to the
2130c6a4ff8STeresa Johnson       // ThinLinkOS if requested so that the expected output file is produced.
2146867ab7cSVlad Tsyrklevich       WriteBitcodeToFile(M, *ThinLinkOS, /*ShouldPreserveUseListOrder=*/false,
2156867ab7cSVlad Tsyrklevich                          &Index);
2166867ab7cSVlad Tsyrklevich 
2171398a32eSPeter Collingbourne     return;
2181398a32eSPeter Collingbourne   }
2191398a32eSPeter Collingbourne 
2201398a32eSPeter Collingbourne   promoteTypeIds(M, ModuleId);
2211398a32eSPeter Collingbourne 
222dd968219SPeter Collingbourne   // Returns whether a global or its associated global has attached type
223dd968219SPeter Collingbourne   // metadata. The former may participate in CFI or whole-program
224dd968219SPeter Collingbourne   // devirtualization, so they need to appear in the merged module instead of
225dd968219SPeter Collingbourne   // the thin LTO module. Similarly, globals that are associated with globals
226dd968219SPeter Collingbourne   // with type metadata need to appear in the merged module because they will
227dd968219SPeter Collingbourne   // reference the global's section directly.
2280deb9a9aSBenjamin Kramer   auto HasTypeMetadata = [](const GlobalObject *GO) {
229dd968219SPeter Collingbourne     if (MDNode *MD = GO->getMetadata(LLVMContext::MD_associated))
230dd968219SPeter Collingbourne       if (auto *AssocVM = dyn_cast_or_null<ValueAsMetadata>(MD->getOperand(0)))
231dd968219SPeter Collingbourne         if (auto *AssocGO = dyn_cast<GlobalObject>(AssocVM->getValue()))
232dd968219SPeter Collingbourne           if (AssocGO->hasMetadata(LLVMContext::MD_type))
233dd968219SPeter Collingbourne             return true;
2340deb9a9aSBenjamin Kramer     return GO->hasMetadata(LLVMContext::MD_type);
2351398a32eSPeter Collingbourne   };
2361398a32eSPeter Collingbourne 
237002c2d53SPeter Collingbourne   // Collect the set of virtual functions that are eligible for virtual constant
238002c2d53SPeter Collingbourne   // propagation. Each eligible function must not access memory, must return
239002c2d53SPeter Collingbourne   // an integer of width <=64 bits, must take at least one argument, must not
240002c2d53SPeter Collingbourne   // use its first argument (assumed to be "this") and all arguments other than
241002c2d53SPeter Collingbourne   // the first one must be of <=64 bit integer type.
242002c2d53SPeter Collingbourne   //
243002c2d53SPeter Collingbourne   // Note that we test whether this copy of the function is readnone, rather
244002c2d53SPeter Collingbourne   // than testing function attributes, which must hold for any copy of the
245002c2d53SPeter Collingbourne   // function, even a less optimized version substituted at link time. This is
246002c2d53SPeter Collingbourne   // sound because the virtual constant propagation optimizations effectively
247002c2d53SPeter Collingbourne   // inline all implementations of the virtual function into each call site,
248002c2d53SPeter Collingbourne   // rather than using function attributes to perform local optimization.
249aa09a82bSGeorge Burgess IV   DenseSet<const Function *> EligibleVirtualFns;
2504075ccc7SBob Haarman   // If any member of a comdat lives in MergedM, put all members of that
2514075ccc7SBob Haarman   // comdat in MergedM to keep the comdat together.
2524075ccc7SBob Haarman   DenseSet<const Comdat *> MergedMComdats;
253002c2d53SPeter Collingbourne   for (GlobalVariable &GV : M.globals())
2544075ccc7SBob Haarman     if (HasTypeMetadata(&GV)) {
2554075ccc7SBob Haarman       if (const auto *C = GV.getComdat())
2564075ccc7SBob Haarman         MergedMComdats.insert(C);
257002c2d53SPeter Collingbourne       forEachVirtualFunction(GV.getInitializer(), [&](Function *F) {
258002c2d53SPeter Collingbourne         auto *RT = dyn_cast<IntegerType>(F->getReturnType());
259002c2d53SPeter Collingbourne         if (!RT || RT->getBitWidth() > 64 || F->arg_empty() ||
260002c2d53SPeter Collingbourne             !F->arg_begin()->use_empty())
261002c2d53SPeter Collingbourne           return;
262002c2d53SPeter Collingbourne         for (auto &Arg : make_range(std::next(F->arg_begin()), F->arg_end())) {
263002c2d53SPeter Collingbourne           auto *ArgT = dyn_cast<IntegerType>(Arg.getType());
264002c2d53SPeter Collingbourne           if (!ArgT || ArgT->getBitWidth() > 64)
265002c2d53SPeter Collingbourne             return;
266002c2d53SPeter Collingbourne         }
26701f0c8a8SChandler Carruth         if (!F->isDeclaration() &&
26801f0c8a8SChandler Carruth             computeFunctionBodyMemoryAccess(*F, AARGetter(*F)) == MAK_ReadNone)
269002c2d53SPeter Collingbourne           EligibleVirtualFns.insert(F);
270002c2d53SPeter Collingbourne       });
2714075ccc7SBob Haarman     }
272002c2d53SPeter Collingbourne 
2731398a32eSPeter Collingbourne   ValueToValueMapTy VMap;
274002c2d53SPeter Collingbourne   std::unique_ptr<Module> MergedM(
27571867532SRafael Espindola       CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
2764075ccc7SBob Haarman         if (const auto *C = GV->getComdat())
2774075ccc7SBob Haarman           if (MergedMComdats.count(C))
2784075ccc7SBob Haarman             return true;
279002c2d53SPeter Collingbourne         if (auto *F = dyn_cast<Function>(GV))
280002c2d53SPeter Collingbourne           return EligibleVirtualFns.count(F);
281002c2d53SPeter Collingbourne         if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV->getBaseObject()))
282002c2d53SPeter Collingbourne           return HasTypeMetadata(GVar);
283002c2d53SPeter Collingbourne         return false;
284002c2d53SPeter Collingbourne       }));
28528ffd326SPeter Collingbourne   StripDebugInfo(*MergedM);
28629c6f483SPeter Collingbourne   MergedM->setModuleInlineAsm("");
2871398a32eSPeter Collingbourne 
288002c2d53SPeter Collingbourne   for (Function &F : *MergedM)
289002c2d53SPeter Collingbourne     if (!F.isDeclaration()) {
290002c2d53SPeter Collingbourne       // Reset the linkage of all functions eligible for virtual constant
291002c2d53SPeter Collingbourne       // propagation. The canonical definitions live in the thin LTO module so
292002c2d53SPeter Collingbourne       // that they can be imported.
293002c2d53SPeter Collingbourne       F.setLinkage(GlobalValue::AvailableExternallyLinkage);
294002c2d53SPeter Collingbourne       F.setComdat(nullptr);
295002c2d53SPeter Collingbourne     }
296002c2d53SPeter Collingbourne 
2974d4ee93dSEvgeniy Stepanov   SetVector<GlobalValue *> CfiFunctions;
2984d4ee93dSEvgeniy Stepanov   for (auto &F : M)
2994d4ee93dSEvgeniy Stepanov     if ((!F.hasLocalLinkage() || F.hasAddressTaken()) && HasTypeMetadata(&F))
3004d4ee93dSEvgeniy Stepanov       CfiFunctions.insert(&F);
3014d4ee93dSEvgeniy Stepanov 
3024075ccc7SBob Haarman   // Remove all globals with type metadata, globals with comdats that live in
3034075ccc7SBob Haarman   // MergedM, and aliases pointing to such globals from the thin LTO module.
304002c2d53SPeter Collingbourne   filterModule(&M, [&](const GlobalValue *GV) {
305002c2d53SPeter Collingbourne     if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV->getBaseObject()))
3064075ccc7SBob Haarman       if (HasTypeMetadata(GVar))
3074075ccc7SBob Haarman         return false;
3084075ccc7SBob Haarman     if (const auto *C = GV->getComdat())
3094075ccc7SBob Haarman       if (MergedMComdats.count(C))
3104075ccc7SBob Haarman         return false;
311002c2d53SPeter Collingbourne     return true;
312002c2d53SPeter Collingbourne   });
3131398a32eSPeter Collingbourne 
3144d4ee93dSEvgeniy Stepanov   promoteInternals(*MergedM, M, ModuleId, CfiFunctions);
3154d4ee93dSEvgeniy Stepanov   promoteInternals(M, *MergedM, ModuleId, CfiFunctions);
3164d4ee93dSEvgeniy Stepanov 
317230b2567SVlad Tsyrklevich   auto &Ctx = MergedM->getContext();
3184d4ee93dSEvgeniy Stepanov   SmallVector<MDNode *, 8> CfiFunctionMDs;
3194d4ee93dSEvgeniy Stepanov   for (auto V : CfiFunctions) {
3204d4ee93dSEvgeniy Stepanov     Function &F = *cast<Function>(V);
3214d4ee93dSEvgeniy Stepanov     SmallVector<MDNode *, 2> Types;
3224d4ee93dSEvgeniy Stepanov     F.getMetadata(LLVMContext::MD_type, Types);
3234d4ee93dSEvgeniy Stepanov 
3244d4ee93dSEvgeniy Stepanov     SmallVector<Metadata *, 4> Elts;
3254d4ee93dSEvgeniy Stepanov     Elts.push_back(MDString::get(Ctx, F.getName()));
3264d4ee93dSEvgeniy Stepanov     CfiFunctionLinkage Linkage;
3270e497d15SPeter Collingbourne     if (lowertypetests::isJumpTableCanonical(&F))
3284d4ee93dSEvgeniy Stepanov       Linkage = CFL_Definition;
3290e497d15SPeter Collingbourne     else if (F.hasExternalWeakLinkage())
3304d4ee93dSEvgeniy Stepanov       Linkage = CFL_WeakDeclaration;
3314d4ee93dSEvgeniy Stepanov     else
3324d4ee93dSEvgeniy Stepanov       Linkage = CFL_Declaration;
3334d4ee93dSEvgeniy Stepanov     Elts.push_back(ConstantAsMetadata::get(
3344d4ee93dSEvgeniy Stepanov         llvm::ConstantInt::get(Type::getInt8Ty(Ctx), Linkage)));
3354d4ee93dSEvgeniy Stepanov     for (auto Type : Types)
3364d4ee93dSEvgeniy Stepanov       Elts.push_back(Type);
3374d4ee93dSEvgeniy Stepanov     CfiFunctionMDs.push_back(MDTuple::get(Ctx, Elts));
3384d4ee93dSEvgeniy Stepanov   }
3394d4ee93dSEvgeniy Stepanov 
3404d4ee93dSEvgeniy Stepanov   if(!CfiFunctionMDs.empty()) {
3414d4ee93dSEvgeniy Stepanov     NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("cfi.functions");
3424d4ee93dSEvgeniy Stepanov     for (auto MD : CfiFunctionMDs)
3434d4ee93dSEvgeniy Stepanov       NMD->addOperand(MD);
3444d4ee93dSEvgeniy Stepanov   }
3451398a32eSPeter Collingbourne 
346cdec22efSVlad Tsyrklevich   SmallVector<MDNode *, 8> FunctionAliases;
347cdec22efSVlad Tsyrklevich   for (auto &A : M.aliases()) {
348cdec22efSVlad Tsyrklevich     if (!isa<Function>(A.getAliasee()))
349cdec22efSVlad Tsyrklevich       continue;
350cdec22efSVlad Tsyrklevich 
351cdec22efSVlad Tsyrklevich     auto *F = cast<Function>(A.getAliasee());
352cdec22efSVlad Tsyrklevich 
3530deb9a9aSBenjamin Kramer     Metadata *Elts[] = {
3540deb9a9aSBenjamin Kramer         MDString::get(Ctx, A.getName()),
3550deb9a9aSBenjamin Kramer         MDString::get(Ctx, F->getName()),
3560deb9a9aSBenjamin Kramer         ConstantAsMetadata::get(
3570deb9a9aSBenjamin Kramer             ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())),
3580deb9a9aSBenjamin Kramer         ConstantAsMetadata::get(
3590deb9a9aSBenjamin Kramer             ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())),
3600deb9a9aSBenjamin Kramer     };
361cdec22efSVlad Tsyrklevich 
362cdec22efSVlad Tsyrklevich     FunctionAliases.push_back(MDTuple::get(Ctx, Elts));
363cdec22efSVlad Tsyrklevich   }
364cdec22efSVlad Tsyrklevich 
365cdec22efSVlad Tsyrklevich   if (!FunctionAliases.empty()) {
366cdec22efSVlad Tsyrklevich     NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("aliases");
367cdec22efSVlad Tsyrklevich     for (auto MD : FunctionAliases)
368cdec22efSVlad Tsyrklevich       NMD->addOperand(MD);
369cdec22efSVlad Tsyrklevich   }
370cdec22efSVlad Tsyrklevich 
371230b2567SVlad Tsyrklevich   SmallVector<MDNode *, 8> Symvers;
372230b2567SVlad Tsyrklevich   ModuleSymbolTable::CollectAsmSymvers(M, [&](StringRef Name, StringRef Alias) {
373230b2567SVlad Tsyrklevich     Function *F = M.getFunction(Name);
374230b2567SVlad Tsyrklevich     if (!F || F->use_empty())
375230b2567SVlad Tsyrklevich       return;
376230b2567SVlad Tsyrklevich 
3770deb9a9aSBenjamin Kramer     Symvers.push_back(MDTuple::get(
3780deb9a9aSBenjamin Kramer         Ctx, {MDString::get(Ctx, Name), MDString::get(Ctx, Alias)}));
379230b2567SVlad Tsyrklevich   });
380230b2567SVlad Tsyrklevich 
381230b2567SVlad Tsyrklevich   if (!Symvers.empty()) {
382230b2567SVlad Tsyrklevich     NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("symvers");
383230b2567SVlad Tsyrklevich     for (auto MD : Symvers)
384230b2567SVlad Tsyrklevich       NMD->addOperand(MD);
385230b2567SVlad Tsyrklevich   }
386230b2567SVlad Tsyrklevich 
3871398a32eSPeter Collingbourne   simplifyExternals(*MergedM);
3881398a32eSPeter Collingbourne 
3891398a32eSPeter Collingbourne   // FIXME: Try to re-use BSI and PFI from the original module here.
39094624acaSTeresa Johnson   ProfileSummaryInfo PSI(M);
39194624acaSTeresa Johnson   ModuleSummaryIndex Index = buildModuleSummaryIndex(M, nullptr, &PSI);
3920c6a4ff8STeresa Johnson 
393e357fbd2SPeter Collingbourne   // Mark the merged module as requiring full LTO. We still want an index for
394e357fbd2SPeter Collingbourne   // it though, so that it can participate in summary-based dead stripping.
395e357fbd2SPeter Collingbourne   MergedM->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
396e357fbd2SPeter Collingbourne   ModuleSummaryIndex MergedMIndex =
397e357fbd2SPeter Collingbourne       buildModuleSummaryIndex(*MergedM, nullptr, &PSI);
398e357fbd2SPeter Collingbourne 
3990c6a4ff8STeresa Johnson   SmallVector<char, 0> Buffer;
4000c6a4ff8STeresa Johnson 
4010c6a4ff8STeresa Johnson   BitcodeWriter W(Buffer);
4020c6a4ff8STeresa Johnson   // Save the module hash produced for the full bitcode, which will
4030c6a4ff8STeresa Johnson   // be used in the backends, and use that in the minimized bitcode
4040c6a4ff8STeresa Johnson   // produced for the full link.
4050c6a4ff8STeresa Johnson   ModuleHash ModHash = {{0}};
4066a86e25dSRafael Espindola   W.writeModule(M, /*ShouldPreserveUseListOrder=*/false, &Index,
4070c6a4ff8STeresa Johnson                 /*GenerateHash=*/true, &ModHash);
4086a86e25dSRafael Espindola   W.writeModule(*MergedM, /*ShouldPreserveUseListOrder=*/false, &MergedMIndex);
40992648c25SPeter Collingbourne   W.writeSymtab();
410a0f371a1SPeter Collingbourne   W.writeStrtab();
4111398a32eSPeter Collingbourne   OS << Buffer;
4120c6a4ff8STeresa Johnson 
4131dec57d5SHaojie Wang   // If a minimized bitcode module was requested for the thin link, only
4141dec57d5SHaojie Wang   // the information that is needed by thin link will be written in the
4151dec57d5SHaojie Wang   // given OS (the merged module will be written as usual).
4160c6a4ff8STeresa Johnson   if (ThinLinkOS) {
4170c6a4ff8STeresa Johnson     Buffer.clear();
4180c6a4ff8STeresa Johnson     BitcodeWriter W2(Buffer);
4190c6a4ff8STeresa Johnson     StripDebugInfo(M);
4206a86e25dSRafael Espindola     W2.writeThinLinkBitcode(M, Index, ModHash);
4216a86e25dSRafael Espindola     W2.writeModule(*MergedM, /*ShouldPreserveUseListOrder=*/false,
422e357fbd2SPeter Collingbourne                    &MergedMIndex);
42392648c25SPeter Collingbourne     W2.writeSymtab();
424a0f371a1SPeter Collingbourne     W2.writeStrtab();
4250c6a4ff8STeresa Johnson     *ThinLinkOS << Buffer;
4260c6a4ff8STeresa Johnson   }
4271398a32eSPeter Collingbourne }
4281398a32eSPeter Collingbourne 
429a7004363STeresa Johnson // Check if the LTO Unit splitting has been enabled.
430a7004363STeresa Johnson bool enableSplitLTOUnit(Module &M) {
431290a8398STeresa Johnson   bool EnableSplitLTOUnit = false;
432290a8398STeresa Johnson   if (auto *MD = mdconst::extract_or_null<ConstantInt>(
433290a8398STeresa Johnson           M.getModuleFlag("EnableSplitLTOUnit")))
434290a8398STeresa Johnson     EnableSplitLTOUnit = MD->getZExtValue();
435a7004363STeresa Johnson   return EnableSplitLTOUnit;
436a7004363STeresa Johnson }
437290a8398STeresa Johnson 
438a7004363STeresa Johnson // Returns whether this module needs to be split because it uses type metadata.
439a7004363STeresa Johnson bool hasTypeMetadata(Module &M) {
4401398a32eSPeter Collingbourne   for (auto &GO : M.global_objects()) {
4410deb9a9aSBenjamin Kramer     if (GO.hasMetadata(LLVMContext::MD_type))
4421398a32eSPeter Collingbourne       return true;
4431398a32eSPeter Collingbourne   }
4441398a32eSPeter Collingbourne   return false;
4451398a32eSPeter Collingbourne }
4461398a32eSPeter Collingbourne 
4470c6a4ff8STeresa Johnson void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS,
448002c2d53SPeter Collingbourne                          function_ref<AAResults &(Function &)> AARGetter,
449002c2d53SPeter Collingbourne                          Module &M, const ModuleSummaryIndex *Index) {
450a7004363STeresa Johnson   std::unique_ptr<ModuleSummaryIndex> NewIndex = nullptr;
451a7004363STeresa Johnson   // See if this module has any type metadata. If so, we try to split it
452a7004363STeresa Johnson   // or at least promote type ids to enable WPD.
453a7004363STeresa Johnson   if (hasTypeMetadata(M)) {
454a7004363STeresa Johnson     if (enableSplitLTOUnit(M))
4550c6a4ff8STeresa Johnson       return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M);
456a7004363STeresa Johnson     // Promote type ids as needed for index-based WPD.
457a7004363STeresa Johnson     std::string ModuleId = getUniqueModuleId(&M);
458a7004363STeresa Johnson     if (!ModuleId.empty()) {
459a7004363STeresa Johnson       promoteTypeIds(M, ModuleId);
460a7004363STeresa Johnson       // Need to rebuild the index so that it contains type metadata
461a7004363STeresa Johnson       // for the newly promoted type ids.
462a7004363STeresa Johnson       // FIXME: Probably should not bother building the index at all
463a7004363STeresa Johnson       // in the caller of writeThinLTOBitcode (which does so via the
464a7004363STeresa Johnson       // ModuleSummaryIndexAnalysis pass), since we have to rebuild it
465a7004363STeresa Johnson       // anyway whenever there is type metadata (here or in
466a7004363STeresa Johnson       // splitAndWriteThinLTOBitcode). Just always build it once via the
467a7004363STeresa Johnson       // buildModuleSummaryIndex when Module(s) are ready.
468a7004363STeresa Johnson       ProfileSummaryInfo PSI(M);
469*0eaee545SJonas Devlieghere       NewIndex = std::make_unique<ModuleSummaryIndex>(
470a7004363STeresa Johnson           buildModuleSummaryIndex(M, nullptr, &PSI));
471a7004363STeresa Johnson       Index = NewIndex.get();
472a7004363STeresa Johnson     }
473a7004363STeresa Johnson   }
4741398a32eSPeter Collingbourne 
475a7004363STeresa Johnson   // Write it out as an unsplit ThinLTO module.
4760c6a4ff8STeresa Johnson 
4770c6a4ff8STeresa Johnson   // Save the module hash produced for the full bitcode, which will
4780c6a4ff8STeresa Johnson   // be used in the backends, and use that in the minimized bitcode
4790c6a4ff8STeresa Johnson   // produced for the full link.
4800c6a4ff8STeresa Johnson   ModuleHash ModHash = {{0}};
4816a86e25dSRafael Espindola   WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false, Index,
4820c6a4ff8STeresa Johnson                      /*GenerateHash=*/true, &ModHash);
4831dec57d5SHaojie Wang   // If a minimized bitcode module was requested for the thin link, only
4841dec57d5SHaojie Wang   // the information that is needed by thin link will be written in the
4851dec57d5SHaojie Wang   // given OS.
4861dec57d5SHaojie Wang   if (ThinLinkOS && Index)
4876a86e25dSRafael Espindola     WriteThinLinkBitcodeToFile(M, *ThinLinkOS, *Index, ModHash);
4881398a32eSPeter Collingbourne }
4891398a32eSPeter Collingbourne 
4901398a32eSPeter Collingbourne class WriteThinLTOBitcode : public ModulePass {
4911398a32eSPeter Collingbourne   raw_ostream &OS; // raw_ostream to print on
4920c6a4ff8STeresa Johnson   // The output stream on which to emit a minimized module for use
4930c6a4ff8STeresa Johnson   // just in the thin link, if requested.
4940c6a4ff8STeresa Johnson   raw_ostream *ThinLinkOS;
4951398a32eSPeter Collingbourne 
4961398a32eSPeter Collingbourne public:
4971398a32eSPeter Collingbourne   static char ID; // Pass identification, replacement for typeid
4980c6a4ff8STeresa Johnson   WriteThinLTOBitcode() : ModulePass(ID), OS(dbgs()), ThinLinkOS(nullptr) {
4991398a32eSPeter Collingbourne     initializeWriteThinLTOBitcodePass(*PassRegistry::getPassRegistry());
5001398a32eSPeter Collingbourne   }
5011398a32eSPeter Collingbourne 
5020c6a4ff8STeresa Johnson   explicit WriteThinLTOBitcode(raw_ostream &o, raw_ostream *ThinLinkOS)
5030c6a4ff8STeresa Johnson       : ModulePass(ID), OS(o), ThinLinkOS(ThinLinkOS) {
5041398a32eSPeter Collingbourne     initializeWriteThinLTOBitcodePass(*PassRegistry::getPassRegistry());
5051398a32eSPeter Collingbourne   }
5061398a32eSPeter Collingbourne 
5071398a32eSPeter Collingbourne   StringRef getPassName() const override { return "ThinLTO Bitcode Writer"; }
5081398a32eSPeter Collingbourne 
5091398a32eSPeter Collingbourne   bool runOnModule(Module &M) override {
5101398a32eSPeter Collingbourne     const ModuleSummaryIndex *Index =
5111398a32eSPeter Collingbourne         &(getAnalysis<ModuleSummaryIndexWrapperPass>().getIndex());
5120c6a4ff8STeresa Johnson     writeThinLTOBitcode(OS, ThinLinkOS, LegacyAARGetter(*this), M, Index);
5131398a32eSPeter Collingbourne     return true;
5141398a32eSPeter Collingbourne   }
5151398a32eSPeter Collingbourne   void getAnalysisUsage(AnalysisUsage &AU) const override {
5161398a32eSPeter Collingbourne     AU.setPreservesAll();
517002c2d53SPeter Collingbourne     AU.addRequired<AssumptionCacheTracker>();
5181398a32eSPeter Collingbourne     AU.addRequired<ModuleSummaryIndexWrapperPass>();
519002c2d53SPeter Collingbourne     AU.addRequired<TargetLibraryInfoWrapperPass>();
5201398a32eSPeter Collingbourne   }
5211398a32eSPeter Collingbourne };
5221398a32eSPeter Collingbourne } // anonymous namespace
5231398a32eSPeter Collingbourne 
5241398a32eSPeter Collingbourne char WriteThinLTOBitcode::ID = 0;
5251398a32eSPeter Collingbourne INITIALIZE_PASS_BEGIN(WriteThinLTOBitcode, "write-thinlto-bitcode",
5261398a32eSPeter Collingbourne                       "Write ThinLTO Bitcode", false, true)
527002c2d53SPeter Collingbourne INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
5281398a32eSPeter Collingbourne INITIALIZE_PASS_DEPENDENCY(ModuleSummaryIndexWrapperPass)
529002c2d53SPeter Collingbourne INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
5301398a32eSPeter Collingbourne INITIALIZE_PASS_END(WriteThinLTOBitcode, "write-thinlto-bitcode",
5311398a32eSPeter Collingbourne                     "Write ThinLTO Bitcode", false, true)
5321398a32eSPeter Collingbourne 
5330c6a4ff8STeresa Johnson ModulePass *llvm::createWriteThinLTOBitcodePass(raw_ostream &Str,
5340c6a4ff8STeresa Johnson                                                 raw_ostream *ThinLinkOS) {
5350c6a4ff8STeresa Johnson   return new WriteThinLTOBitcode(Str, ThinLinkOS);
5361398a32eSPeter Collingbourne }
5376b411418STim Shen 
5386b411418STim Shen PreservedAnalyses
5396b411418STim Shen llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) {
5406b411418STim Shen   FunctionAnalysisManager &FAM =
5416b411418STim Shen       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
5426b411418STim Shen   writeThinLTOBitcode(OS, ThinLinkOS,
5436b411418STim Shen                       [&FAM](Function &F) -> AAResults & {
5446b411418STim Shen                         return FAM.getResult<AAManager>(F);
5456b411418STim Shen                       },
5466b411418STim Shen                       M, &AM.getResult<ModuleSummaryIndexAnalysis>(M));
5476b411418STim Shen   return PreservedAnalyses::all();
5486b411418STim Shen }
549