From: David Green Date: Wed, 12 Sep 2018 14:09:06 +0000 (+0000) Subject: [CodeGen] Align rtti and vtable data X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d2ada3f873df854259dcf3016d2bec54c562fdbe;p=clang [CodeGen] Align rtti and vtable data Previously the alignment on the newly created rtti/typeinfo data was largely not set, meaning that DataLayout::getPreferredAlignment was free to overalign it to 16 bytes. This causes unnecessary code bloat. Differential Revision: https://reviews.llvm.org/D51416 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342053 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp index b0a3a0bffa..fbd8146702 100644 --- a/lib/CodeGen/CGVTT.cpp +++ b/lib/CodeGen/CGVTT.cpp @@ -119,10 +119,10 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { llvm::ArrayType *ArrayType = llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size()); + unsigned Align = CGM.getDataLayout().getABITypeAlignment(CGM.Int8PtrTy); - llvm::GlobalVariable *GV = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, - llvm::GlobalValue::ExternalLinkage); + llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( + Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); return GV; } diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index d07c160e24..df20b9bb46 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -756,9 +756,11 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) Linkage = llvm::GlobalVariable::InternalLinkage; + unsigned Align = CGM.getDataLayout().getABITypeAlignment(VTType); + // Create the variable that will hold the construction vtable. llvm::GlobalVariable *VTable = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage); + CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align); CGM.setGVProperties(VTable, RD); // V-tables are always unnamed_addr. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5fec6c7bcb..6d42b3ca79 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3099,10 +3099,9 @@ CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, IsForDefinition); } -llvm::GlobalVariable * -CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, - llvm::Type *Ty, - llvm::GlobalValue::LinkageTypes Linkage) { +llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable( + StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage, + unsigned Alignment) { llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name); llvm::GlobalVariable *OldGV = nullptr; @@ -3138,6 +3137,8 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, !GV->hasAvailableExternallyLinkage()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + GV->setAlignment(Alignment); + return GV; } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 91f3d94330..ae7f7f3e19 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -764,7 +764,8 @@ public: /// bitcast to the new variable. llvm::GlobalVariable * CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, - llvm::GlobalValue::LinkageTypes Linkage); + llvm::GlobalValue::LinkageTypes Linkage, + unsigned Alignment); llvm::Function * CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name, diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index b2a8f5a945..a7e3c8d58b 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1598,12 +1598,6 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, // Set the right visibility. CGM.setGVProperties(VTable, RD); - // Use pointer alignment for the vtable. Otherwise we would align them based - // on the size of the initializer which doesn't make sense as only single - // values are read. - unsigned PAlign = CGM.getTarget().getPointerAlign(0); - VTable->setAlignment(getContext().toCharUnitsFromBits(PAlign).getQuantity()); - // If this is the magic class __cxxabiv1::__fundamental_type_info, // we will emit the typeinfo for the fundamental types. This is the // same behaviour as GCC. @@ -1703,8 +1697,14 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CGM.getItaniumVTableContext().getVTableLayout(RD); llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); + // Use pointer alignment for the vtable. Otherwise we would align them based + // on the size of the initializer which doesn't make sense as only single + // values are read. + unsigned PAlign = CGM.getTarget().getPointerAlign(0); + VTable = CGM.CreateOrReplaceCXXRuntimeVariable( - Name, VTableType, llvm::GlobalValue::ExternalLinkage); + Name, VTableType, llvm::GlobalValue::ExternalLinkage, + getContext().toCharUnitsFromBits(PAlign).getQuantity()); VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); CGM.setGVProperties(VTable, RD); @@ -2725,9 +2725,10 @@ llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName( // get the mangled name of the type. llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext, Name.substr(4)); + auto Align = CGM.getContext().getTypeAlignInChars(CGM.getContext().CharTy); - llvm::GlobalVariable *GV = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage); + llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( + Name, Init->getType(), Linkage, Align.getQuantity()); GV->setInitializer(Init); @@ -3366,6 +3367,10 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( if (CGM.supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(M.getOrInsertComdat(GV->getName())); + CharUnits Align = + CGM.getContext().toCharUnitsFromBits(CGM.getTarget().getPointerAlign(0)); + GV->setAlignment(Align.getQuantity()); + // The Itanium ABI specifies that type_info objects must be globally // unique, with one exception: if the type is an incomplete class // type or a (possibly indirect) pointer to one. That exception diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 968c171c71..3b894fcdc1 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2024,8 +2024,10 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, assert(!CGM.getModule().getNamedGlobal(Name) && "vbtable with this name already exists: mangling bug?"); - llvm::GlobalVariable *GV = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType, Linkage); + CharUnits Alignment = + CGM.getContext().getTypeAlignInChars(CGM.getContext().IntTy); + llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( + Name, VBTableType, Linkage, Alignment.getQuantity()); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); if (RD->hasAttr()) diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp index 46e159c628..ae6602053b 100644 --- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp @@ -19,7 +19,7 @@ D d; // Force vbtable emission. // C: vbptr C // int c -// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20] +// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20], comdat, align 4 // CHECK-DAG: @"??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4] // CHECK-DAG: @"??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12] // CHECK-DAG: @"??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8] diff --git a/test/CodeGenCXX/vtable-align.cpp b/test/CodeGenCXX/vtable-align.cpp index 1b82cbc085..bd0494fe5d 100644 --- a/test/CodeGenCXX/vtable-align.cpp +++ b/test/CodeGenCXX/vtable-align.cpp @@ -10,5 +10,8 @@ struct A { void A::f() {} // CHECK-32: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 4 - +// CHECK-32: @_ZTS1A = constant [3 x i8] c"1A\00", align 1 +// CHECK-32: @_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) }, align 4 // CHECK-64: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 8 +// CHECK-64: @_ZTS1A = constant [3 x i8] c"1A\00", align 1 +// CHECK-64: @_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) }, align 8 diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index 0c55eb26f7..d4f06ce6ce 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -98,10 +98,10 @@ void use_F() { // C has no key function, so its vtable should have weak_odr linkage // and hidden visibility (rdar://problem/7523229). -// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, align 8{{$}} +// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat, align 8{{$}} +// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, align 8{{$}} // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. @@ -120,27 +120,27 @@ void use_F() { // defined in this translation unit, so its vtable should have // weak_odr linkage. // CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat, align 8{{$}} // F is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage // CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat, align 8{{$}} // E is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // linkonce_odr linkage. // CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat, align 8{{$}} // F is an implicit template instantiation with no key function, // so its vtable should have linkonce_odr linkage. // CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat, align 8{{$}} // F is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. @@ -171,8 +171,8 @@ void use_F() { // F is an explicit specialization without a key function, so // its vtable should have linkonce_odr linkage. // CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat, align 8{{$}} // CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant {{.*}}, comdat, template