[clang] Don't emit type test/assume for virtual classes that should never participate in WPD

Reviewed By: pcc

Differential Revision: https://reviews.llvm.org/D127876
This commit is contained in:
Arthur Eubanks 2022-06-15 09:44:43 -07:00
parent 046ebeb605
commit a70b39abff
6 changed files with 25 additions and 24 deletions

View File

@ -35,13 +35,14 @@ other classes receive hidden LTO visibility. Classes with internal linkage
(e.g. classes declared in unnamed namespaces) also receive hidden LTO (e.g. classes declared in unnamed namespaces) also receive hidden LTO
visibility. visibility.
During the LTO link, all classes with public LTO visibility will be refined During the LTO link, all classes with public LTO visibility but not marked with
to hidden LTO visibility when the ``--lto-whole-program-visibility`` lld linker ``[[clang::lto_visibility_public]]`` (see below) will be refined to hidden LTO
option is applied (``-plugin-opt=whole-program-visibility`` for gold). This flag visibility when the ``--lto-whole-program-visibility`` lld linker option is
can be used to defer specifying whether classes have hidden LTO visibility until applied (``-plugin-opt=whole-program-visibility`` for gold). This flag can be
link time, to allow bitcode objects to be shared by different LTO links. used to defer specifying whether classes have hidden LTO visibility until link
Due to an implementation limitation, symbols associated with classes with hidden time, to allow bitcode objects to be shared by different LTO links. Due to an
LTO visibility may still be exported from the binary when using this flag. It is implementation limitation, symbols associated with classes with hidden LTO
visibility may still be exported from the binary when using this flag. It is
unsafe to refer to these symbols, and their visibility may be relaxed to hidden unsafe to refer to these symbols, and their visibility may be relaxed to hidden
in a future compiler release. in a future compiler release.

View File

@ -2695,9 +2695,9 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
if (SanOpts.has(SanitizerKind::CFIVCall)) if (SanOpts.has(SanitizerKind::CFIVCall))
EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc); EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
else if (CGM.getCodeGenOpts().WholeProgramVTables && else if (CGM.getCodeGenOpts().WholeProgramVTables &&
// Don't insert type test assumes if we are forcing public std // Don't insert type test assumes if we are forcing public
// visibility. // visibility.
!CGM.HasLTOVisibilityPublicStd(RD)) { !CGM.AlwaysHasLTOVisibilityPublic(RD)) {
llvm::Metadata *MD = llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
llvm::Value *TypeId = llvm::Value *TypeId =

View File

@ -1175,7 +1175,10 @@ void CodeGenModule::EmitDeferredVTables() {
DeferredVTables.clear(); DeferredVTables.clear();
} }
bool CodeGenModule::HasLTOVisibilityPublicStd(const CXXRecordDecl *RD) { bool CodeGenModule::AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD) {
if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>())
return true;
if (!getCodeGenOpts().LTOVisibilityPublicStd) if (!getCodeGenOpts().LTOVisibilityPublicStd)
return false; return false;
@ -1200,9 +1203,6 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
if (!isExternallyVisible(LV.getLinkage())) if (!isExternallyVisible(LV.getLinkage()))
return true; return true;
if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>())
return false;
if (getTriple().isOSBinFormatCOFF()) { if (getTriple().isOSBinFormatCOFF()) {
if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>()) if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>())
return false; return false;
@ -1211,7 +1211,7 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
return false; return false;
} }
return !HasLTOVisibilityPublicStd(RD); return !AlwaysHasLTOVisibilityPublic(RD);
} }
llvm::GlobalObject::VCallVisibility CodeGenModule::GetVCallVisibilityLevel( llvm::GlobalObject::VCallVisibility CodeGenModule::GetVCallVisibilityLevel(

View File

@ -1382,10 +1382,10 @@ public:
/// optimization. /// optimization.
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD); bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);
/// Returns whether the given record has public std LTO visibility /// Returns whether the given record has public LTO visibility (regardless of
/// and therefore may not participate in (single-module) CFI and whole-program /// -lto-whole-program-visibility) and therefore may not participate in
/// vtable optimization. /// (single-module) CFI and whole-program vtable optimization.
bool HasLTOVisibilityPublicStd(const CXXRecordDecl *RD); bool AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD);
/// Returns the vcall visibility of the given type. This is the scope in which /// Returns the vcall visibility of the given type. This is the scope in which
/// a virtual function call could be made which ends up being dispatched to a /// a virtual function call could be made which ends up being dispatched to a

View File

@ -668,8 +668,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CGM.HasHiddenLTOVisibility(RD); CGM.HasHiddenLTOVisibility(RD);
bool ShouldEmitWPDInfo = bool ShouldEmitWPDInfo =
CGM.getCodeGenOpts().WholeProgramVTables && CGM.getCodeGenOpts().WholeProgramVTables &&
// Don't insert type tests if we are forcing public std visibility. // Don't insert type tests if we are forcing public visibility.
!CGM.HasLTOVisibilityPublicStd(RD); !CGM.AlwaysHasLTOVisibilityPublic(RD);
llvm::Value *VirtualFn = nullptr; llvm::Value *VirtualFn = nullptr;
{ {

View File

@ -79,11 +79,11 @@ void f(C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, std::C7 *c7,
// ITANIUM: type.test{{.*}}!"_ZTS2C4" // ITANIUM: type.test{{.*}}!"_ZTS2C4"
// MS: type.test{{.*}}!"?AUC4@@" // MS: type.test{{.*}}!"?AUC4@@"
c4->f(); c4->f();
// ITANIUM: type.test{{.*}}!"_ZTS2C5" // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C5"
// MS: type.test{{.*}}!"?AUC5@@" // MS-NOT: type.test{{.*}}!"?AUC5@@"
c5->f(); c5->f();
// ITANIUM: type.test{{.*}}!"_ZTS2C6" // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C6"
// MS: type.test{{.*}}!"?AUC6@@" // MS-NOT: type.test{{.*}}!"?AUC6@@"
c6->f(); c6->f();
// ITANIUM: type.test{{.*}}!"_ZTSSt2C7" // ITANIUM: type.test{{.*}}!"_ZTSSt2C7"
// MS-STD: type.test{{.*}}!"?AUC7@std@@" // MS-STD: type.test{{.*}}!"?AUC7@std@@"