Skip to content

Commit 43c85af

Browse files
authored
ThinLTOBitcodeWriter: Split modules with __cfi_check and no type metadata.
Eli Friedman found a case that was not handled correctly by #154833 where we failed to split the module if it contained a __cfi_check function but no type metadata. Handle this case correctly by checking for __cfi_check when deciding whether to split. Reviewers: teresajohnson, efriedma-quic Reviewed By: efriedma-quic Pull Request: #155930
1 parent 2a062d6 commit 43c85af

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ static bool enableUnifiedLTO(Module &M) {
269269
}
270270
#endif
271271

272+
bool mustEmitToMergedModule(const GlobalValue *GV) {
273+
// The __cfi_check definition is filled in by the CrossDSOCFI pass which
274+
// runs only in the merged module.
275+
return GV->getName() == "__cfi_check";
276+
}
277+
272278
// If it's possible to split M into regular and thin LTO parts, do so and write
273279
// a multi-module bitcode file with the two parts to OS. Otherwise, write only a
274280
// regular LTO bitcode file to OS.
@@ -350,19 +356,13 @@ void splitAndWriteThinLTOBitcode(
350356
});
351357
}
352358

353-
auto MustEmitToMergedModule = [](const GlobalValue *GV) {
354-
// The __cfi_check definition is filled in by the CrossDSOCFI pass which
355-
// runs only in the merged module.
356-
return GV->getName() == "__cfi_check";
357-
};
358-
359359
ValueToValueMapTy VMap;
360360
std::unique_ptr<Module> MergedM(
361361
CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
362362
if (const auto *C = GV->getComdat())
363363
if (MergedMComdats.count(C))
364364
return true;
365-
if (MustEmitToMergedModule(GV))
365+
if (mustEmitToMergedModule(GV))
366366
return true;
367367
if (auto *F = dyn_cast<Function>(GV))
368368
return EligibleVirtualFns.count(F);
@@ -380,7 +380,7 @@ void splitAndWriteThinLTOBitcode(
380380
cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true);
381381

382382
for (Function &F : *MergedM)
383-
if (!F.isDeclaration() && !MustEmitToMergedModule(&F)) {
383+
if (!F.isDeclaration() && !mustEmitToMergedModule(&F)) {
384384
// Reset the linkage of all functions eligible for virtual constant
385385
// propagation. The canonical definitions live in the thin LTO module so
386386
// that they can be imported.
@@ -406,7 +406,7 @@ void splitAndWriteThinLTOBitcode(
406406
if (const auto *C = GV->getComdat())
407407
if (MergedMComdats.count(C))
408408
return false;
409-
if (MustEmitToMergedModule(GV))
409+
if (mustEmitToMergedModule(GV))
410410
return false;
411411
return true;
412412
});
@@ -529,11 +529,13 @@ bool enableSplitLTOUnit(Module &M) {
529529
return EnableSplitLTOUnit;
530530
}
531531

532-
// Returns whether this module needs to be split because it uses type metadata.
533-
bool hasTypeMetadata(Module &M) {
532+
// Returns whether this module needs to be split (if splitting is enabled).
533+
bool requiresSplit(Module &M) {
534534
for (auto &GO : M.global_objects()) {
535535
if (GO.hasMetadata(LLVMContext::MD_type))
536536
return true;
537+
if (mustEmitToMergedModule(&GO))
538+
return true;
537539
}
538540
return false;
539541
}
@@ -543,9 +545,9 @@ bool writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS,
543545
Module &M, const ModuleSummaryIndex *Index,
544546
const bool ShouldPreserveUseListOrder) {
545547
std::unique_ptr<ModuleSummaryIndex> NewIndex = nullptr;
546-
// See if this module has any type metadata. If so, we try to split it
548+
// See if this module needs to be split. If so, we try to split it
547549
// or at least promote type ids to enable WPD.
548-
if (hasTypeMetadata(M)) {
550+
if (requiresSplit(M)) {
549551
if (enableSplitLTOUnit(M)) {
550552
splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M,
551553
ShouldPreserveUseListOrder);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
2+
; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
3+
; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
4+
5+
; Check that __cfi_check is emitted on the full LTO side with
6+
; attributes preserved, even if nothing has !type metadata
7+
; on the ThinLTO side.
8+
9+
; M0: @g = global i32 0
10+
@g = global i32 0
11+
12+
; M1: define void @__cfi_check() #0
13+
define void @__cfi_check() #0 {
14+
ret void
15+
}
16+
17+
; M1: attributes #0 = { "branch-target-enforcement" }
18+
attributes #0 = { "branch-target-enforcement" }

0 commit comments

Comments
 (0)