[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
visibility.
During the LTO link, all classes with public LTO visibility will be refined
to hidden LTO visibility when the ``--lto-whole-program-visibility`` lld linker
option is applied (``-plugin-opt=whole-program-visibility`` for gold). This flag
can be used to defer specifying whether classes have hidden LTO visibility until
link time, to allow bitcode objects to be shared by different LTO links.
Due to an implementation limitation, symbols associated with classes with hidden
LTO visibility may still be exported from the binary when using this flag. It is
During the LTO link, all classes with public LTO visibility but not marked with
``[[clang::lto_visibility_public]]`` (see below) will be refined to hidden LTO
visibility when the ``--lto-whole-program-visibility`` lld linker option is
applied (``-plugin-opt=whole-program-visibility`` for gold). This flag can be
used to defer specifying whether classes have hidden LTO visibility until link
time, to allow bitcode objects to be shared by different LTO links. Due to an
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
in a future compiler release.

View File

@ -2695,9 +2695,9 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
if (SanOpts.has(SanitizerKind::CFIVCall))
EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
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.
!CGM.HasLTOVisibilityPublicStd(RD)) {
!CGM.AlwaysHasLTOVisibilityPublic(RD)) {
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
llvm::Value *TypeId =

View File

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

View File

@ -1382,10 +1382,10 @@ public:
/// optimization.
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);
/// Returns whether the given record has public std LTO visibility
/// and therefore may not participate in (single-module) CFI and whole-program
/// vtable optimization.
bool HasLTOVisibilityPublicStd(const CXXRecordDecl *RD);
/// Returns whether the given record has public LTO visibility (regardless of
/// -lto-whole-program-visibility) and therefore may not participate in
/// (single-module) CFI and whole-program vtable optimization.
bool AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD);
/// 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

View File

@ -668,8 +668,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CGM.HasHiddenLTOVisibility(RD);
bool ShouldEmitWPDInfo =
CGM.getCodeGenOpts().WholeProgramVTables &&
// Don't insert type tests if we are forcing public std visibility.
!CGM.HasLTOVisibilityPublicStd(RD);
// Don't insert type tests if we are forcing public visibility.
!CGM.AlwaysHasLTOVisibilityPublic(RD);
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"
// MS: type.test{{.*}}!"?AUC4@@"
c4->f();
// ITANIUM: type.test{{.*}}!"_ZTS2C5"
// MS: type.test{{.*}}!"?AUC5@@"
// ITANIUM-NOT: type.test{{.*}}!"_ZTS2C5"
// MS-NOT: type.test{{.*}}!"?AUC5@@"
c5->f();
// ITANIUM: type.test{{.*}}!"_ZTS2C6"
// MS: type.test{{.*}}!"?AUC6@@"
// ITANIUM-NOT: type.test{{.*}}!"_ZTS2C6"
// MS-NOT: type.test{{.*}}!"?AUC6@@"
c6->f();
// ITANIUM: type.test{{.*}}!"_ZTSSt2C7"
// MS-STD: type.test{{.*}}!"?AUC7@std@@"