Skip to content

Commit 5973352

Browse files
committed
[LTO/WPD] Enable aggressive WPD under LTO option
Summary: Third part in series to support Safe Whole Program Devirtualization Enablement, see RFC here: http://lists.llvm.org/pipermail/llvm-dev/2019-December/137543.html This patch adds type test metadata under -fwhole-program-vtables, even for classes without hidden visibility. It then changes WPD to skip devirtualization for a virtual function call when any of the compatible vtables has public vcall visibility. Additionally, internal LLVM options as well as lld and gold-plugin options are added which enable upgrading all public vcall visibility to linkage unit (hidden) visibility during LTO. This enables the more aggressive WPD to kick in based on LTO time knowledge of the visibility guarantees. Support was added to all flavors of LTO WPD (regular, hybrid and index-only), and to both the new and old LTO APIs. Unfortunately it was not simple to split the first and second parts of this part of the change (the unconditional emission of type tests and the upgrading of the vcall visiblity) as I needed a way to upgrade the public visibility on legacy WPD llvm assembly tests that don't include linkage unit vcall visibility specifiers, to avoid a lot of test churn. I also added a mechanism to LowerTypeTests that allows dropping type test assume sequences we now aggressively insert when we invoke distributed ThinLTO backends with null indexes, which is used in testing mode, and which doesn't invoke the normal ThinLTO backend pipeline. Depends on D71907 and D71911. Reviewers: pcc, evgeny777, steven_wu, espindola Subscribers: emaste, Prazek, inglorion, arichardson, hiraditya, MaskRay, dexonsmith, dang, davidxl, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D71913
1 parent 9e66c4e commit 5973352

File tree

71 files changed

+1046
-93
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1046
-93
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "llvm/Transforms/Coroutines.h"
5252
#include "llvm/Transforms/IPO.h"
5353
#include "llvm/Transforms/IPO/AlwaysInliner.h"
54+
#include "llvm/Transforms/IPO/LowerTypeTests.h"
5455
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
5556
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
5657
#include "llvm/Transforms/InstCombine/InstCombine.h"
@@ -553,6 +554,16 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
553554
std::unique_ptr<TargetLibraryInfoImpl> TLII(
554555
createTLII(TargetTriple, CodeGenOpts));
555556

557+
// If we reached here with a non-empty index file name, then the index file
558+
// was empty and we are not performing ThinLTO backend compilation (used in
559+
// testing in a distributed build environment). Drop any the type test
560+
// assume sequences inserted for whole program vtables so that codegen doesn't
561+
// complain.
562+
if (!CodeGenOpts.ThinLTOIndexFile.empty())
563+
MPM.add(createLowerTypeTestsPass(/*ExportSummary=*/nullptr,
564+
/*ImportSummary=*/nullptr,
565+
/*DropTypeTests=*/true));
566+
556567
PassManagerBuilderWrapper PMBuilder(TargetTriple, CodeGenOpts, LangOpts);
557568

558569
// At O0 and O1 we only run the always inliner which is more efficient. At
@@ -1114,6 +1125,15 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
11141125
bool IsLTO = CodeGenOpts.PrepareForLTO;
11151126

11161127
if (CodeGenOpts.OptimizationLevel == 0) {
1128+
// If we reached here with a non-empty index file name, then the index
1129+
// file was empty and we are not performing ThinLTO backend compilation
1130+
// (used in testing in a distributed build environment). Drop any the type
1131+
// test assume sequences inserted for whole program vtables so that
1132+
// codegen doesn't complain.
1133+
if (!CodeGenOpts.ThinLTOIndexFile.empty())
1134+
MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,
1135+
/*ImportSummary=*/nullptr,
1136+
/*DropTypeTests=*/true));
11171137
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts))
11181138
MPM.addPass(GCOVProfilerPass(*Options));
11191139
if (Optional<InstrProfOptions> Options =
@@ -1150,6 +1170,18 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
11501170
// configure the pipeline.
11511171
PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts);
11521172

1173+
// If we reached here with a non-empty index file name, then the index
1174+
// file was empty and we are not performing ThinLTO backend compilation
1175+
// (used in testing in a distributed build environment). Drop any the type
1176+
// test assume sequences inserted for whole program vtables so that
1177+
// codegen doesn't complain.
1178+
if (!CodeGenOpts.ThinLTOIndexFile.empty())
1179+
PB.registerPipelineStartEPCallback([](ModulePassManager &MPM) {
1180+
MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,
1181+
/*ImportSummary=*/nullptr,
1182+
/*DropTypeTests=*/true));
1183+
});
1184+
11531185
PB.registerPipelineStartEPCallback([](ModulePassManager &MPM) {
11541186
MPM.addPass(createModuleToFunctionPassAdaptor(
11551187
EntryExitInstrumenterPass(/*PostInlining=*/false)));

clang/lib/CodeGen/CGClass.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2641,7 +2641,9 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
26412641
if (SanOpts.has(SanitizerKind::CFIVCall))
26422642
EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
26432643
else if (CGM.getCodeGenOpts().WholeProgramVTables &&
2644-
CGM.HasHiddenLTOVisibility(RD)) {
2644+
// Don't insert type test assumes if we are forcing public std
2645+
// visibility.
2646+
!CGM.HasLTOVisibilityPublicStd(RD)) {
26452647
llvm::Metadata *MD =
26462648
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
26472649
llvm::Value *TypeId =

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,26 @@ void CodeGenModule::EmitDeferredVTables() {
10111011
DeferredVTables.clear();
10121012
}
10131013

1014+
bool CodeGenModule::HasLTOVisibilityPublicStd(const CXXRecordDecl *RD) {
1015+
if (!getCodeGenOpts().LTOVisibilityPublicStd)
1016+
return false;
1017+
1018+
const DeclContext *DC = RD;
1019+
while (1) {
1020+
auto *D = cast<Decl>(DC);
1021+
DC = DC->getParent();
1022+
if (isa<TranslationUnitDecl>(DC->getRedeclContext())) {
1023+
if (auto *ND = dyn_cast<NamespaceDecl>(D))
1024+
if (const IdentifierInfo *II = ND->getIdentifier())
1025+
if (II->isStr("std") || II->isStr("stdext"))
1026+
return true;
1027+
break;
1028+
}
1029+
}
1030+
1031+
return false;
1032+
}
1033+
10141034
bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
10151035
LinkageInfo LV = RD->getLinkageAndVisibility();
10161036
if (!isExternallyVisible(LV.getLinkage()))
@@ -1027,22 +1047,7 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
10271047
return false;
10281048
}
10291049

1030-
if (getCodeGenOpts().LTOVisibilityPublicStd) {
1031-
const DeclContext *DC = RD;
1032-
while (1) {
1033-
auto *D = cast<Decl>(DC);
1034-
DC = DC->getParent();
1035-
if (isa<TranslationUnitDecl>(DC->getRedeclContext())) {
1036-
if (auto *ND = dyn_cast<NamespaceDecl>(D))
1037-
if (const IdentifierInfo *II = ND->getIdentifier())
1038-
if (II->isStr("std") || II->isStr("stdext"))
1039-
return false;
1040-
break;
1041-
}
1042-
}
1043-
}
1044-
1045-
return true;
1050+
return !HasLTOVisibilityPublicStd(RD);
10461051
}
10471052

10481053
llvm::GlobalObject::VCallVisibility

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,11 @@ class CodeGenModule : public CodeGenTypeCache {
12921292
/// optimization.
12931293
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);
12941294

1295+
/// Returns whether the given record has public std LTO visibility
1296+
/// and therefore may not participate in (single-module) CFI and whole-program
1297+
/// vtable optimization.
1298+
bool HasLTOVisibilityPublicStd(const CXXRecordDecl *RD);
1299+
12951300
/// Returns the vcall visibility of the given type. This is the scope in which
12961301
/// a virtual function call could be made which ends up being dispatched to a
12971302
/// member function of this class. This scope can be wider than the visibility

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -670,15 +670,20 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
670670
CGM.HasHiddenLTOVisibility(RD);
671671
bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
672672
CGM.HasHiddenLTOVisibility(RD);
673+
bool ShouldEmitWPDInfo =
674+
CGM.getCodeGenOpts().WholeProgramVTables &&
675+
// Don't insert type tests if we are forcing public std visibility.
676+
!CGM.HasLTOVisibilityPublicStd(RD);
673677
llvm::Value *VirtualFn = nullptr;
674678

675679
{
676680
CodeGenFunction::SanitizerScope SanScope(&CGF);
677681
llvm::Value *TypeId = nullptr;
678682
llvm::Value *CheckResult = nullptr;
679683

680-
if (ShouldEmitCFICheck || ShouldEmitVFEInfo) {
681-
// If doing CFI or VFE, we will need the metadata node to check against.
684+
if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
685+
// If doing CFI, VFE or WPD, we will need the metadata node to check
686+
// against.
682687
llvm::Metadata *MD =
683688
CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
684689
TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
@@ -702,7 +707,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
702707
} else {
703708
// When not doing VFE, emit a normal load, as it allows more
704709
// optimisations than type.checked.load.
705-
if (ShouldEmitCFICheck) {
710+
if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
706711
CheckResult = Builder.CreateCall(
707712
CGM.getIntrinsic(llvm::Intrinsic::type_test),
708713
{Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
@@ -713,7 +718,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
713718
"memptr.virtualfn");
714719
}
715720
assert(VirtualFn && "Virtual fuction pointer not created!");
716-
assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || CheckResult) &&
721+
assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
722+
CheckResult) &&
717723
"Check result required but not created!");
718724

719725
if (ShouldEmitCFICheck) {

clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
; FIXME: Fix machine verifier issues and remove -verify-machineinstrs=0. PR39436.
1010
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
11+
; RUN: -whole-program-visibility \
1112
; RUN: -verify-machineinstrs=0 \
1213
; RUN: -o %t2.index \
1314
; RUN: -r=%t.o,test,px \

clang/test/CodeGenCXX/cfi-mfcall.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s
22
// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility default -emit-llvm -o - %s | FileCheck --check-prefix=DEFAULT %s
3+
// With -fwhole-program-vtables we should get the member function pointer type
4+
// test, even without hidden visibility.
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck %s --check-prefix=WPV
36

47
struct B1 {};
58
struct B2 {};
@@ -9,6 +12,9 @@ struct S : B1, B3 {};
912
// DEFAULT-NOT: llvm.type.test
1013

1114
void f(S *s, void (S::*p)()) {
15+
// WPV: [[OFFSET:%.*]] = sub i64 {{.*}}, 1
16+
// WPV: [[VFPTR:%.*]] = getelementptr i8, i8* %{{.*}}, i64 [[OFFSET]]
17+
// WPV: [[TT:%.*]] = call i1 @llvm.type.test(i8* [[VFPTR]], metadata !"_ZTSM1SFvvE.virtual")
1218
// CHECK: [[OFFSET:%.*]] = sub i64 {{.*}}, 1
1319
// CHECK: [[VFPTR:%.*]] = getelementptr i8, i8* %{{.*}}, i64 [[OFFSET]]
1420
// CHECK: [[TT:%.*]] = call i1 @llvm.type.test(i8* [[VFPTR]], metadata !"_ZTSM1SFvvE.virtual")

clang/test/CodeGenCXX/lto-visibility-inference.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,20 @@ void f(C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, std::C7 *c7,
7070
// ITANIUM: type.test{{.*}}!"_ZTS2C1"
7171
// MS: type.test{{.*}}!"?AUC1@@"
7272
c1->f();
73-
// ITANIUM-NOT: type.test{{.*}}!"_ZTS2C2"
73+
// ITANIUM: type.test{{.*}}!"_ZTS2C2"
7474
// MS: type.test{{.*}}!"?AUC2@@"
7575
c2->f();
7676
// ITANIUM: type.test{{.*}}!"_ZTS2C3"
77-
// MS-NOT: type.test{{.*}}!"?AUC3@@"
77+
// MS: type.test{{.*}}!"?AUC3@@"
7878
c3->f();
7979
// ITANIUM: type.test{{.*}}!"_ZTS2C4"
80-
// MS-NOT: type.test{{.*}}!"?AUC4@@"
80+
// MS: type.test{{.*}}!"?AUC4@@"
8181
c4->f();
82-
// ITANIUM-NOT: type.test{{.*}}!"_ZTS2C5"
83-
// MS-NOT: type.test{{.*}}!"?AUC5@@"
82+
// ITANIUM: type.test{{.*}}!"_ZTS2C5"
83+
// MS: type.test{{.*}}!"?AUC5@@"
8484
c5->f();
85-
// ITANIUM-NOT: type.test{{.*}}!"_ZTS2C6"
86-
// MS-NOT: type.test{{.*}}!"?AUC6@@"
85+
// ITANIUM: type.test{{.*}}!"_ZTS2C6"
86+
// MS: type.test{{.*}}!"?AUC6@@"
8787
c6->f();
8888
// ITANIUM: type.test{{.*}}!"_ZTSSt2C7"
8989
// MS-STD: type.test{{.*}}!"?AUC7@std@@"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Test distributed ThinLTO backend handling of type tests
2+
3+
// REQUIRES: x86-registered-target
4+
5+
// Ensure that a distributed backend invocation of ThinLTO lowers the type test
6+
// as expected.
7+
// RUN: %clang_cc1 -flto=thin -flto-unit -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm-bc -o %t.o %s
8+
// RUN: llvm-dis %t.o -o - | FileCheck --check-prefix=TT %s
9+
// RUN: llvm-lto -thinlto -o %t2 %t.o
10+
// RUN: %clang -target x86_64-unknown-linux -O2 -o %t3.o -x ir %t.o -c -fthinlto-index=%t2.thinlto.bc -save-temps=obj
11+
// RUN: llvm-dis %t.s.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
12+
// llvm-nm %t3.o | FileCheck --check-prefix=NM %s
13+
14+
// The pre-link bitcode produced by clang should contain a type test assume
15+
// sequence.
16+
// TT: [[TTREG:%[0-9]+]] = call i1 @llvm.type.test({{.*}}, metadata !"_ZTS1A")
17+
// TT: void @llvm.assume(i1 [[TTREG]])
18+
19+
// The ThinLTO backend optimized bitcode should not have any type test assume
20+
// sequences.
21+
// OPT-NOT: @llvm.type.test
22+
// OPT-NOT: call void @llvm.assume
23+
// We should have only one @llvm.assume call, the one that was expanded
24+
// from the builtin in the IR below, not the one fed by the type test.
25+
// OPT: %cmp = icmp ne %struct.A* %0, null
26+
// OPT: void @llvm.assume(i1 %cmp)
27+
// Check after the builtin assume again that we don't have a type test assume
28+
// sequence.
29+
// OPT-NOT: @llvm.type.test
30+
// OPT-NOT: call void @llvm.assume
31+
32+
// NM: T _Z2afP1A
33+
34+
// Also check type test are lowered when the distributed ThinLTO backend clang
35+
// invocation is passed an empty index file, in which case a non-ThinLTO
36+
// compilation pipeline is invoked. If not lowered then LLVM CodeGen may assert.
37+
// RUN: touch %t4.thinlto.bc
38+
// O2 old PM
39+
// RUN: %clang -target x86_64-unknown-linux -O2 -o %t4.o -x ir %t.o -c -fthinlto-index=%t4.thinlto.bc -save-temps=obj
40+
// RUN: llvm-dis %t.s.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
41+
// llvm-nm %t4.o | FileCheck --check-prefix=NM %s
42+
// O2 new PM
43+
// RUN: %clang -target x86_64-unknown-linux -O2 -o %t4.o -x ir %t.o -c -fthinlto-index=%t4.thinlto.bc -fexperimental-new-pass-manager -save-temps=obj
44+
// RUN: llvm-dis %t.s.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
45+
// llvm-nm %t4.o | FileCheck --check-prefix=NM %s
46+
// O0 new PM
47+
// RUN: %clang -target x86_64-unknown-linux -O0 -o %t4.o -x ir %t.o -c -fthinlto-index=%t4.thinlto.bc -fexperimental-new-pass-manager -save-temps=obj
48+
// RUN: llvm-dis %t.s.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
49+
// llvm-nm %t4.o | FileCheck --check-prefix=NM %s
50+
51+
struct A {
52+
A();
53+
virtual void f();
54+
};
55+
56+
struct B : virtual A {
57+
B();
58+
};
59+
60+
A::A() {}
61+
B::B() {}
62+
63+
void A::f() {
64+
}
65+
66+
void af(A *a) {
67+
__builtin_assume(a != 0);
68+
a->f();
69+
}

clang/test/CodeGenCXX/type-metadata.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
// Tests for the whole-program-vtables feature:
88
// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM %s
9+
// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM-DEFAULTVIS --check-prefix=TT-ITANIUM %s
910
// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS --check-prefix=TT-MS %s
1011

1112
// Tests for cfi + whole-program-vtables:
@@ -129,6 +130,7 @@ void D::h() {
129130
}
130131

131132
// ITANIUM: define hidden void @_Z2afP1A
133+
// ITANIUM-DEFAULTVIS: define void @_Z2afP1A
132134
// MS: define dso_local void @"?af@@YAXPEAUA@@@Z"
133135
void af(A *a) {
134136
// TT-ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
@@ -239,6 +241,7 @@ struct D : C {
239241
};
240242

241243
// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE
244+
// ITANIUM-DEFAULTVIS: define void @_ZN5test21fEPNS_1DE
242245
// MS: define dso_local void @"?f@test2@@YAXPEAUD@1@@Z"
243246
void f(D *d) {
244247
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ struct Configuration {
165165
bool ltoCSProfileGenerate;
166166
bool ltoDebugPassManager;
167167
bool ltoNewPassManager;
168+
bool ltoWholeProgramVisibility;
168169
bool mergeArmExidx;
169170
bool mipsN32Abi = false;
170171
bool mmapOutputFile;

lld/ELF/Driver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,8 @@ static void readConfigs(opt::InputArgList &args) {
899899
config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
900900
config->ltoNewPassManager = args.hasArg(OPT_lto_new_pass_manager);
901901
config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
902+
config->ltoWholeProgramVisibility =
903+
args.hasArg(OPT_lto_whole_program_visibility);
902904
config->ltoo = args::getInteger(args, OPT_lto_O, 2);
903905
config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq);
904906
config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);

lld/ELF/LTO.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ static lto::Config createConfig() {
111111
c.DebugPassManager = config->ltoDebugPassManager;
112112
c.DwoDir = config->dwoDir;
113113

114+
c.HasWholeProgramVisibility = config->ltoWholeProgramVisibility;
115+
114116
c.CSIRProfile = config->ltoCSProfileFile;
115117
c.RunCSIRInstr = config->ltoCSProfileGenerate;
116118

lld/ELF/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ def lto_cs_profile_file: J<"lto-cs-profile-file=">,
479479
def lto_obj_path_eq: J<"lto-obj-path=">;
480480
def lto_sample_profile: J<"lto-sample-profile=">,
481481
HelpText<"Sample profile file path">;
482+
def lto_whole_program_visibility: F<"lto-whole-program-visibility">,
483+
HelpText<"Asserts that the LTO link has whole program visibility">;
482484
def disable_verify: F<"disable-verify">;
483485
defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">;
484486
def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">,

0 commit comments

Comments
 (0)