1 //===- ThinLTOBitcodeWriter.cpp - Bitcode writing pass for ThinLTO --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
10 #include "llvm/Analysis/BasicAliasAnalysis.h"
11 #include "llvm/Analysis/ModuleSummaryAnalysis.h"
12 #include "llvm/Analysis/ProfileSummaryInfo.h"
13 #include "llvm/Analysis/TypeMetadataUtils.h"
14 #include "llvm/Bitcode/BitcodeWriter.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/DebugInfo.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/Intrinsics.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/IR/PassManager.h"
21 #include "llvm/InitializePasses.h"
22 #include "llvm/Object/ModuleSymbolTable.h"
23 #include "llvm/Pass.h"
24 #include "llvm/Support/ScopedPrinter.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Transforms/IPO.h"
27 #include "llvm/Transforms/IPO/FunctionAttrs.h"
28 #include "llvm/Transforms/IPO/FunctionImport.h"
29 #include "llvm/Transforms/IPO/LowerTypeTests.h"
30 #include "llvm/Transforms/Utils/Cloning.h"
31 #include "llvm/Transforms/Utils/ModuleUtils.h"
32 using namespace llvm;
33
34 namespace {
35
36 // Promote each local-linkage entity defined by ExportM and used by ImportM by
37 // changing visibility and appending the given ModuleId.
promoteInternals(Module & ExportM,Module & ImportM,StringRef ModuleId,SetVector<GlobalValue * > & PromoteExtra)38 void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
39 SetVector<GlobalValue *> &PromoteExtra) {
40 DenseMap<const Comdat *, Comdat *> RenamedComdats;
41 for (auto &ExportGV : ExportM.global_values()) {
42 if (!ExportGV.hasLocalLinkage())
43 continue;
44
45 auto Name = ExportGV.getName();
46 GlobalValue *ImportGV = nullptr;
47 if (!PromoteExtra.count(&ExportGV)) {
48 ImportGV = ImportM.getNamedValue(Name);
49 if (!ImportGV)
50 continue;
51 ImportGV->removeDeadConstantUsers();
52 if (ImportGV->use_empty()) {
53 ImportGV->eraseFromParent();
54 continue;
55 }
56 }
57
58 std::string NewName = (Name + ModuleId).str();
59
60 if (const auto *C = ExportGV.getComdat())
61 if (C->getName() == Name)
62 RenamedComdats.try_emplace(C, ExportM.getOrInsertComdat(NewName));
63
64 ExportGV.setName(NewName);
65 ExportGV.setLinkage(GlobalValue::ExternalLinkage);
66 ExportGV.setVisibility(GlobalValue::HiddenVisibility);
67
68 if (ImportGV) {
69 ImportGV->setName(NewName);
70 ImportGV->setVisibility(GlobalValue::HiddenVisibility);
71 }
72 }
73
74 if (!RenamedComdats.empty())
75 for (auto &GO : ExportM.global_objects())
76 if (auto *C = GO.getComdat()) {
77 auto Replacement = RenamedComdats.find(C);
78 if (Replacement != RenamedComdats.end())
79 GO.setComdat(Replacement->second);
80 }
81 }
82
83 // Promote all internal (i.e. distinct) type ids used by the module by replacing
84 // them with external type ids formed using the module id.
85 //
86 // Note that this needs to be done before we clone the module because each clone
87 // will receive its own set of distinct metadata nodes.
promoteTypeIds(Module & M,StringRef ModuleId)88 void promoteTypeIds(Module &M, StringRef ModuleId) {
89 DenseMap<Metadata *, Metadata *> LocalToGlobal;
90 auto ExternalizeTypeId = [&](CallInst *CI, unsigned ArgNo) {
91 Metadata *MD =
92 cast<MetadataAsValue>(CI->getArgOperand(ArgNo))->getMetadata();
93
94 if (isa<MDNode>(MD) && cast<MDNode>(MD)->isDistinct()) {
95 Metadata *&GlobalMD = LocalToGlobal[MD];
96 if (!GlobalMD) {
97 std::string NewName = (Twine(LocalToGlobal.size()) + ModuleId).str();
98 GlobalMD = MDString::get(M.getContext(), NewName);
99 }
100
101 CI->setArgOperand(ArgNo,
102 MetadataAsValue::get(M.getContext(), GlobalMD));
103 }
104 };
105
106 if (Function *TypeTestFunc =
107 M.getFunction(Intrinsic::getName(Intrinsic::type_test))) {
108 for (const Use &U : TypeTestFunc->uses()) {
109 auto CI = cast<CallInst>(U.getUser());
110 ExternalizeTypeId(CI, 1);
111 }
112 }
113
114 if (Function *TypeCheckedLoadFunc =
115 M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load))) {
116 for (const Use &U : TypeCheckedLoadFunc->uses()) {
117 auto CI = cast<CallInst>(U.getUser());
118 ExternalizeTypeId(CI, 2);
119 }
120 }
121
122 for (GlobalObject &GO : M.global_objects()) {
123 SmallVector<MDNode *, 1> MDs;
124 GO.getMetadata(LLVMContext::MD_type, MDs);
125
126 GO.eraseMetadata(LLVMContext::MD_type);
127 for (auto MD : MDs) {
128 auto I = LocalToGlobal.find(MD->getOperand(1));
129 if (I == LocalToGlobal.end()) {
130 GO.addMetadata(LLVMContext::MD_type, *MD);
131 continue;
132 }
133 GO.addMetadata(
134 LLVMContext::MD_type,
135 *MDNode::get(M.getContext(), {MD->getOperand(0), I->second}));
136 }
137 }
138 }
139
140 // Drop unused globals, and drop type information from function declarations.
141 // FIXME: If we made functions typeless then there would be no need to do this.
simplifyExternals(Module & M)142 void simplifyExternals(Module &M) {
143 FunctionType *EmptyFT =
144 FunctionType::get(Type::getVoidTy(M.getContext()), false);
145
146 for (auto I = M.begin(), E = M.end(); I != E;) {
147 Function &F = *I++;
148 if (F.isDeclaration() && F.use_empty()) {
149 F.eraseFromParent();
150 continue;
151 }
152
153 if (!F.isDeclaration() || F.getFunctionType() == EmptyFT ||
154 // Changing the type of an intrinsic may invalidate the IR.
155 F.getName().startswith("llvm."))
156 continue;
157
158 Function *NewF =
159 Function::Create(EmptyFT, GlobalValue::ExternalLinkage,
160 F.getAddressSpace(), "", &M);
161 NewF->copyAttributesFrom(&F);
162 // Only copy function attribtues.
163 NewF->setAttributes(
164 AttributeList::get(M.getContext(), AttributeList::FunctionIndex,
165 F.getAttributes().getFnAttributes()));
166 NewF->takeName(&F);
167 F.replaceAllUsesWith(ConstantExpr::getBitCast(NewF, F.getType()));
168 F.eraseFromParent();
169 }
170
171 for (auto I = M.global_begin(), E = M.global_end(); I != E;) {
172 GlobalVariable &GV = *I++;
173 if (GV.isDeclaration() && GV.use_empty()) {
174 GV.eraseFromParent();
175 continue;
176 }
177 }
178 }
179
180 static void
filterModule(Module * M,function_ref<bool (const GlobalValue *)> ShouldKeepDefinition)181 filterModule(Module *M,
182 function_ref<bool(const GlobalValue *)> ShouldKeepDefinition) {
183 std::vector<GlobalValue *> V;
184 for (GlobalValue &GV : M->global_values())
185 if (!ShouldKeepDefinition(&GV))
186 V.push_back(&GV);
187
188 for (GlobalValue *GV : V)
189 if (!convertToDeclaration(*GV))
190 GV->eraseFromParent();
191 }
192
forEachVirtualFunction(Constant * C,function_ref<void (Function *)> Fn)193 void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) {
194 if (auto *F = dyn_cast<Function>(C))
195 return Fn(F);
196 if (isa<GlobalValue>(C))
197 return;
198 for (Value *Op : C->operands())
199 forEachVirtualFunction(cast<Constant>(Op), Fn);
200 }
201
202 // Clone any @llvm[.compiler].used over to the new module and append
203 // values whose defs were cloned into that module.
cloneUsedGlobalVariables(const Module & SrcM,Module & DestM,bool CompilerUsed)204 static void cloneUsedGlobalVariables(const Module &SrcM, Module &DestM,
205 bool CompilerUsed) {
206 SmallVector<GlobalValue *, 4> Used, NewUsed;
207 // First collect those in the llvm[.compiler].used set.
208 collectUsedGlobalVariables(SrcM, Used, CompilerUsed);
209 // Next build a set of the equivalent values defined in DestM.
210 for (auto *V : Used) {
211 auto *GV = DestM.getNamedValue(V->getName());
212 if (GV && !GV->isDeclaration())
213 NewUsed.push_back(GV);
214 }
215 // Finally, add them to a llvm[.compiler].used variable in DestM.
216 if (CompilerUsed)
217 appendToCompilerUsed(DestM, NewUsed);
218 else
219 appendToUsed(DestM, NewUsed);
220 }
221
222 // If it's possible to split M into regular and thin LTO parts, do so and write
223 // a multi-module bitcode file with the two parts to OS. Otherwise, write only a
224 // regular LTO bitcode file to OS.
splitAndWriteThinLTOBitcode(raw_ostream & OS,raw_ostream * ThinLinkOS,function_ref<AAResults & (Function &)> AARGetter,Module & M)225 void splitAndWriteThinLTOBitcode(
226 raw_ostream &OS, raw_ostream *ThinLinkOS,
227 function_ref<AAResults &(Function &)> AARGetter, Module &M) {
228 std::string ModuleId = getUniqueModuleId(&M);
229 if (ModuleId.empty()) {
230 // We couldn't generate a module ID for this module, write it out as a
231 // regular LTO module with an index for summary-based dead stripping.
232 ProfileSummaryInfo PSI(M);
233 M.addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
234 ModuleSummaryIndex Index = buildModuleSummaryIndex(M, nullptr, &PSI);
235 WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false, &Index);
236
237 if (ThinLinkOS)
238 // We don't have a ThinLTO part, but still write the module to the
239 // ThinLinkOS if requested so that the expected output file is produced.
240 WriteBitcodeToFile(M, *ThinLinkOS, /*ShouldPreserveUseListOrder=*/false,
241 &Index);
242
243 return;
244 }
245
246 promoteTypeIds(M, ModuleId);
247
248 // Returns whether a global or its associated global has attached type
249 // metadata. The former may participate in CFI or whole-program
250 // devirtualization, so they need to appear in the merged module instead of
251 // the thin LTO module. Similarly, globals that are associated with globals
252 // with type metadata need to appear in the merged module because they will
253 // reference the global's section directly.
254 auto HasTypeMetadata = [](const GlobalObject *GO) {
255 if (MDNode *MD = GO->getMetadata(LLVMContext::MD_associated))
256 if (auto *AssocVM = dyn_cast_or_null<ValueAsMetadata>(MD->getOperand(0)))
257 if (auto *AssocGO = dyn_cast<GlobalObject>(AssocVM->getValue()))
258 if (AssocGO->hasMetadata(LLVMContext::MD_type))
259 return true;
260 return GO->hasMetadata(LLVMContext::MD_type);
261 };
262
263 // Collect the set of virtual functions that are eligible for virtual constant
264 // propagation. Each eligible function must not access memory, must return
265 // an integer of width <=64 bits, must take at least one argument, must not
266 // use its first argument (assumed to be "this") and all arguments other than
267 // the first one must be of <=64 bit integer type.
268 //
269 // Note that we test whether this copy of the function is readnone, rather
270 // than testing function attributes, which must hold for any copy of the
271 // function, even a less optimized version substituted at link time. This is
272 // sound because the virtual constant propagation optimizations effectively
273 // inline all implementations of the virtual function into each call site,
274 // rather than using function attributes to perform local optimization.
275 DenseSet<const Function *> EligibleVirtualFns;
276 // If any member of a comdat lives in MergedM, put all members of that
277 // comdat in MergedM to keep the comdat together.
278 DenseSet<const Comdat *> MergedMComdats;
279 for (GlobalVariable &GV : M.globals())
280 if (HasTypeMetadata(&GV)) {
281 if (const auto *C = GV.getComdat())
282 MergedMComdats.insert(C);
283 forEachVirtualFunction(GV.getInitializer(), [&](Function *F) {
284 auto *RT = dyn_cast<IntegerType>(F->getReturnType());
285 if (!RT || RT->getBitWidth() > 64 || F->arg_empty() ||
286 !F->arg_begin()->use_empty())
287 return;
288 for (auto &Arg : drop_begin(F->args())) {
289 auto *ArgT = dyn_cast<IntegerType>(Arg.getType());
290 if (!ArgT || ArgT->getBitWidth() > 64)
291 return;
292 }
293 if (!F->isDeclaration() &&
294 computeFunctionBodyMemoryAccess(*F, AARGetter(*F)) == MAK_ReadNone)
295 EligibleVirtualFns.insert(F);
296 });
297 }
298
299 ValueToValueMapTy VMap;
300 std::unique_ptr<Module> MergedM(
301 CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
302 if (const auto *C = GV->getComdat())
303 if (MergedMComdats.count(C))
304 return true;
305 if (auto *F = dyn_cast<Function>(GV))
306 return EligibleVirtualFns.count(F);
307 if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV->getBaseObject()))
308 return HasTypeMetadata(GVar);
309 return false;
310 }));
311 StripDebugInfo(*MergedM);
312 MergedM->setModuleInlineAsm("");
313
314 // Clone any llvm.*used globals to ensure the included values are
315 // not deleted.
316 cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ false);
317 cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true);
318
319 for (Function &F : *MergedM)
320 if (!F.isDeclaration()) {
321 // Reset the linkage of all functions eligible for virtual constant
322 // propagation. The canonical definitions live in the thin LTO module so
323 // that they can be imported.
324 F.setLinkage(GlobalValue::AvailableExternallyLinkage);
325 F.setComdat(nullptr);
326 }
327
328 SetVector<GlobalValue *> CfiFunctions;
329 for (auto &F : M)
330 if ((!F.hasLocalLinkage() || F.hasAddressTaken()) && HasTypeMetadata(&F))
331 CfiFunctions.insert(&F);
332
333 // Remove all globals with type metadata, globals with comdats that live in
334 // MergedM, and aliases pointing to such globals from the thin LTO module.
335 filterModule(&M, [&](const GlobalValue *GV) {
336 if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV->getBaseObject()))
337 if (HasTypeMetadata(GVar))
338 return false;
339 if (const auto *C = GV->getComdat())
340 if (MergedMComdats.count(C))
341 return false;
342 return true;
343 });
344
345 promoteInternals(*MergedM, M, ModuleId, CfiFunctions);
346 promoteInternals(M, *MergedM, ModuleId, CfiFunctions);
347
348 auto &Ctx = MergedM->getContext();
349 SmallVector<MDNode *, 8> CfiFunctionMDs;
350 for (auto V : CfiFunctions) {
351 Function &F = *cast<Function>(V);
352 SmallVector<MDNode *, 2> Types;
353 F.getMetadata(LLVMContext::MD_type, Types);
354
355 SmallVector<Metadata *, 4> Elts;
356 Elts.push_back(MDString::get(Ctx, F.getName()));
357 CfiFunctionLinkage Linkage;
358 if (lowertypetests::isJumpTableCanonical(&F))
359 Linkage = CFL_Definition;
360 else if (F.hasExternalWeakLinkage())
361 Linkage = CFL_WeakDeclaration;
362 else
363 Linkage = CFL_Declaration;
364 Elts.push_back(ConstantAsMetadata::get(
365 llvm::ConstantInt::get(Type::getInt8Ty(Ctx), Linkage)));
366 append_range(Elts, Types);
367 CfiFunctionMDs.push_back(MDTuple::get(Ctx, Elts));
368 }
369
370 if(!CfiFunctionMDs.empty()) {
371 NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("cfi.functions");
372 for (auto MD : CfiFunctionMDs)
373 NMD->addOperand(MD);
374 }
375
376 SmallVector<MDNode *, 8> FunctionAliases;
377 for (auto &A : M.aliases()) {
378 if (!isa<Function>(A.getAliasee()))
379 continue;
380
381 auto *F = cast<Function>(A.getAliasee());
382
383 Metadata *Elts[] = {
384 MDString::get(Ctx, A.getName()),
385 MDString::get(Ctx, F->getName()),
386 ConstantAsMetadata::get(
387 ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())),
388 ConstantAsMetadata::get(
389 ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())),
390 };
391
392 FunctionAliases.push_back(MDTuple::get(Ctx, Elts));
393 }
394
395 if (!FunctionAliases.empty()) {
396 NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("aliases");
397 for (auto MD : FunctionAliases)
398 NMD->addOperand(MD);
399 }
400
401 SmallVector<MDNode *, 8> Symvers;
402 ModuleSymbolTable::CollectAsmSymvers(M, [&](StringRef Name, StringRef Alias) {
403 Function *F = M.getFunction(Name);
404 if (!F || F->use_empty())
405 return;
406
407 Symvers.push_back(MDTuple::get(
408 Ctx, {MDString::get(Ctx, Name), MDString::get(Ctx, Alias)}));
409 });
410
411 if (!Symvers.empty()) {
412 NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("symvers");
413 for (auto MD : Symvers)
414 NMD->addOperand(MD);
415 }
416
417 simplifyExternals(*MergedM);
418
419 // FIXME: Try to re-use BSI and PFI from the original module here.
420 ProfileSummaryInfo PSI(M);
421 ModuleSummaryIndex Index = buildModuleSummaryIndex(M, nullptr, &PSI);
422
423 // Mark the merged module as requiring full LTO. We still want an index for
424 // it though, so that it can participate in summary-based dead stripping.
425 MergedM->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
426 ModuleSummaryIndex MergedMIndex =
427 buildModuleSummaryIndex(*MergedM, nullptr, &PSI);
428
429 SmallVector<char, 0> Buffer;
430
431 BitcodeWriter W(Buffer);
432 // Save the module hash produced for the full bitcode, which will
433 // be used in the backends, and use that in the minimized bitcode
434 // produced for the full link.
435 ModuleHash ModHash = {{0}};
436 W.writeModule(M, /*ShouldPreserveUseListOrder=*/false, &Index,
437 /*GenerateHash=*/true, &ModHash);
438 W.writeModule(*MergedM, /*ShouldPreserveUseListOrder=*/false, &MergedMIndex);
439 W.writeSymtab();
440 W.writeStrtab();
441 OS << Buffer;
442
443 // If a minimized bitcode module was requested for the thin link, only
444 // the information that is needed by thin link will be written in the
445 // given OS (the merged module will be written as usual).
446 if (ThinLinkOS) {
447 Buffer.clear();
448 BitcodeWriter W2(Buffer);
449 StripDebugInfo(M);
450 W2.writeThinLinkBitcode(M, Index, ModHash);
451 W2.writeModule(*MergedM, /*ShouldPreserveUseListOrder=*/false,
452 &MergedMIndex);
453 W2.writeSymtab();
454 W2.writeStrtab();
455 *ThinLinkOS << Buffer;
456 }
457 }
458
459 // Check if the LTO Unit splitting has been enabled.
enableSplitLTOUnit(Module & M)460 bool enableSplitLTOUnit(Module &M) {
461 bool EnableSplitLTOUnit = false;
462 if (auto *MD = mdconst::extract_or_null<ConstantInt>(
463 M.getModuleFlag("EnableSplitLTOUnit")))
464 EnableSplitLTOUnit = MD->getZExtValue();
465 return EnableSplitLTOUnit;
466 }
467
468 // Returns whether this module needs to be split because it uses type metadata.
hasTypeMetadata(Module & M)469 bool hasTypeMetadata(Module &M) {
470 for (auto &GO : M.global_objects()) {
471 if (GO.hasMetadata(LLVMContext::MD_type))
472 return true;
473 }
474 return false;
475 }
476
writeThinLTOBitcode(raw_ostream & OS,raw_ostream * ThinLinkOS,function_ref<AAResults & (Function &)> AARGetter,Module & M,const ModuleSummaryIndex * Index)477 void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS,
478 function_ref<AAResults &(Function &)> AARGetter,
479 Module &M, const ModuleSummaryIndex *Index) {
480 std::unique_ptr<ModuleSummaryIndex> NewIndex = nullptr;
481 // See if this module has any type metadata. If so, we try to split it
482 // or at least promote type ids to enable WPD.
483 if (hasTypeMetadata(M)) {
484 if (enableSplitLTOUnit(M))
485 return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M);
486 // Promote type ids as needed for index-based WPD.
487 std::string ModuleId = getUniqueModuleId(&M);
488 if (!ModuleId.empty()) {
489 promoteTypeIds(M, ModuleId);
490 // Need to rebuild the index so that it contains type metadata
491 // for the newly promoted type ids.
492 // FIXME: Probably should not bother building the index at all
493 // in the caller of writeThinLTOBitcode (which does so via the
494 // ModuleSummaryIndexAnalysis pass), since we have to rebuild it
495 // anyway whenever there is type metadata (here or in
496 // splitAndWriteThinLTOBitcode). Just always build it once via the
497 // buildModuleSummaryIndex when Module(s) are ready.
498 ProfileSummaryInfo PSI(M);
499 NewIndex = std::make_unique<ModuleSummaryIndex>(
500 buildModuleSummaryIndex(M, nullptr, &PSI));
501 Index = NewIndex.get();
502 }
503 }
504
505 // Write it out as an unsplit ThinLTO module.
506
507 // Save the module hash produced for the full bitcode, which will
508 // be used in the backends, and use that in the minimized bitcode
509 // produced for the full link.
510 ModuleHash ModHash = {{0}};
511 WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false, Index,
512 /*GenerateHash=*/true, &ModHash);
513 // If a minimized bitcode module was requested for the thin link, only
514 // the information that is needed by thin link will be written in the
515 // given OS.
516 if (ThinLinkOS && Index)
517 WriteThinLinkBitcodeToFile(M, *ThinLinkOS, *Index, ModHash);
518 }
519
520 class WriteThinLTOBitcode : public ModulePass {
521 raw_ostream &OS; // raw_ostream to print on
522 // The output stream on which to emit a minimized module for use
523 // just in the thin link, if requested.
524 raw_ostream *ThinLinkOS;
525
526 public:
527 static char ID; // Pass identification, replacement for typeid
WriteThinLTOBitcode()528 WriteThinLTOBitcode() : ModulePass(ID), OS(dbgs()), ThinLinkOS(nullptr) {
529 initializeWriteThinLTOBitcodePass(*PassRegistry::getPassRegistry());
530 }
531
WriteThinLTOBitcode(raw_ostream & o,raw_ostream * ThinLinkOS)532 explicit WriteThinLTOBitcode(raw_ostream &o, raw_ostream *ThinLinkOS)
533 : ModulePass(ID), OS(o), ThinLinkOS(ThinLinkOS) {
534 initializeWriteThinLTOBitcodePass(*PassRegistry::getPassRegistry());
535 }
536
getPassName() const537 StringRef getPassName() const override { return "ThinLTO Bitcode Writer"; }
538
runOnModule(Module & M)539 bool runOnModule(Module &M) override {
540 const ModuleSummaryIndex *Index =
541 &(getAnalysis<ModuleSummaryIndexWrapperPass>().getIndex());
542 writeThinLTOBitcode(OS, ThinLinkOS, LegacyAARGetter(*this), M, Index);
543 return true;
544 }
getAnalysisUsage(AnalysisUsage & AU) const545 void getAnalysisUsage(AnalysisUsage &AU) const override {
546 AU.setPreservesAll();
547 AU.addRequired<AssumptionCacheTracker>();
548 AU.addRequired<ModuleSummaryIndexWrapperPass>();
549 AU.addRequired<TargetLibraryInfoWrapperPass>();
550 }
551 };
552 } // anonymous namespace
553
554 char WriteThinLTOBitcode::ID = 0;
555 INITIALIZE_PASS_BEGIN(WriteThinLTOBitcode, "write-thinlto-bitcode",
556 "Write ThinLTO Bitcode", false, true)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)557 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
558 INITIALIZE_PASS_DEPENDENCY(ModuleSummaryIndexWrapperPass)
559 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
560 INITIALIZE_PASS_END(WriteThinLTOBitcode, "write-thinlto-bitcode",
561 "Write ThinLTO Bitcode", false, true)
562
563 ModulePass *llvm::createWriteThinLTOBitcodePass(raw_ostream &Str,
564 raw_ostream *ThinLinkOS) {
565 return new WriteThinLTOBitcode(Str, ThinLinkOS);
566 }
567
568 PreservedAnalyses
run(Module & M,ModuleAnalysisManager & AM)569 llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) {
570 FunctionAnalysisManager &FAM =
571 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
572 writeThinLTOBitcode(OS, ThinLinkOS,
573 [&FAM](Function &F) -> AAResults & {
574 return FAM.getResult<AAManager>(F);
575 },
576 M, &AM.getResult<ModuleSummaryIndexAnalysis>(M));
577 return PreservedAnalyses::all();
578 }
579