forked from OSchip/llvm-project
Fix TBAA representation for zero-sized fields and unnamed bit-fields.
Unnamed bit-fields should not be represented in the TBAA metadata because they do not represent storage fields (they only affect layout). Zero-sized fields should not be represented in the TBAA metadata because by definition they have no associated storage (so we will never emit a load or store through them), and they might not appear in declaration order within the struct layout. Fixes a verifier failure when emitting a TBAA-enabled load through a class type containing a zero-sized field. llvm-svn: 364140
This commit is contained in:
parent
780c374b20
commit
1fa07ebd92
|
@ -257,6 +257,8 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
|
|||
unsigned idx = 0;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(),
|
||||
e = RD->field_end(); i != e; ++i, ++idx) {
|
||||
if ((*i)->isZeroSize(Context) || (*i)->isUnnamedBitfield())
|
||||
continue;
|
||||
uint64_t Offset = BaseOffset +
|
||||
Layout.getFieldOffset(idx) / Context.getCharWidth();
|
||||
QualType FieldQTy = i->getType();
|
||||
|
@ -297,6 +299,8 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
|
|||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
|
||||
for (FieldDecl *Field : RD->fields()) {
|
||||
if (Field->isZeroSize(Context) || Field->isUnnamedBitfield())
|
||||
continue;
|
||||
QualType FieldQTy = Field->getType();
|
||||
llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
|
||||
getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
|
||||
|
|
|
@ -111,8 +111,8 @@ void copy7(A *a1, AA *a2) {
|
|||
// CHECK-OLD: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}}
|
||||
// (offset, size) = (0,8) char; (0,2) char; (4,8) char
|
||||
// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
|
||||
// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 4, [[TAG_INT]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
|
||||
// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
|
||||
// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
|
||||
// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
|
||||
|
||||
// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
|
||||
// CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
|
||||
|
@ -123,7 +123,7 @@ void copy7(A *a1, AA *a2) {
|
|||
// CHECK-NEW-DAG: [[TYPE_B:!.*]] = !{[[TYPE_char]], i64 24, !"_ZTS1B", [[TYPE_char]], i64 0, i64 1, [[TYPE_A]], i64 4, i64 16, [[TYPE_int]], i64 20, i64 4}
|
||||
// CHECK-NEW-DAG: [[TAG_B]] = !{[[TYPE_B]], [[TYPE_B]], i64 0, i64 24}
|
||||
// CHECK-NEW-DAG: [[TAG_U]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 12}
|
||||
// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS1C", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1}
|
||||
// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS1C", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1}
|
||||
// CHECK-NEW-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], i64 0, i64 3}
|
||||
// CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
|
||||
// CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
|
||||
// CHECK-NEW-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], i64 0, i64 6}
|
||||
|
|
|
@ -272,9 +272,9 @@ uint32_t g15(StructS *S, StructS3 *S3, uint64_t count) {
|
|||
// OLD-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12}
|
||||
// OLD-PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32}
|
||||
// OLD-PATH: [[TAG_five_b]] = !{[[TYPE_five:!.*]], [[TYPE_CHAR]], i64 1}
|
||||
// OLD-PATH: [[TYPE_five]] = !{!"_ZTS4five", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 1, [[TYPE_CHAR]], i64 1, [[TYPE_CHAR]], i64 2}
|
||||
// OLD-PATH: [[TYPE_five]] = !{!"_ZTS4five", [[TYPE_CHAR]], i64 0, [[TYPE_CHAR]], i64 1, [[TYPE_CHAR]], i64 2}
|
||||
// OLD-PATH: [[TAG_six_b]] = !{[[TYPE_six:!.*]], [[TYPE_CHAR]], i64 4}
|
||||
// OLD-PATH: [[TYPE_six]] = !{!"_ZTS3six", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_CHAR]], i64 4, [[TYPE_CHAR]], i64 5}
|
||||
// OLD-PATH: [[TYPE_six]] = !{!"_ZTS3six", [[TYPE_CHAR]], i64 0, [[TYPE_CHAR]], i64 4, [[TYPE_CHAR]], i64 5}
|
||||
|
||||
// NEW-PATH-DAG: [[ROOT:!.*]] = !{!"Simple C++ TBAA"}
|
||||
// NEW-PATH-DAG: [[TYPE_char:!.*]] = !{[[ROOT]], i64 1, !"omnipotent char"}
|
||||
|
@ -299,7 +299,7 @@ uint32_t g15(StructS *S, StructS3 *S3, uint64_t count) {
|
|||
// NEW-PATH-DAG: [[TAG_C_b_a_f32]] = !{[[TYPE_C]], [[TYPE_int]], i64 12, i64 4}
|
||||
// NEW-PATH-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 36, !"_ZTS7StructD", [[TYPE_short]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_int]], i64 28, i64 4, [[TYPE_char]], i64 32, i64 1}
|
||||
// NEW-PATH-DAG: [[TAG_D_b_a_f32]] = !{[[TYPE_D]], [[TYPE_int]], i64 12, i64 4}
|
||||
// NEW-PATH-DAG: [[TYPE_five:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS4five", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1}
|
||||
// NEW-PATH-DAG: [[TYPE_five:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS4five", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1}
|
||||
// NEW-PATH-DAG: [[TAG_five_b]] = !{[[TYPE_five]], [[TYPE_char]], i64 1, i64 1}
|
||||
// NEW-PATH-DAG: [[TYPE_six:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS3six", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
|
||||
// NEW-PATH-DAG: [[TYPE_six:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS3six", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
|
||||
// NEW-PATH-DAG: [[TAG_six_b]] = !{[[TYPE_six]], [[TYPE_char]], i64 4, i64 1}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cc1 -std=c++2a %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s
|
||||
// RUN: %clang_cc1 -std=c++2a %s -emit-llvm -o - -triple x86_64-linux-gnu -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-OPT
|
||||
|
||||
struct A { ~A(); int n; char c[3]; };
|
||||
struct B { [[no_unique_address]] A a; char k; };
|
||||
|
@ -77,3 +78,18 @@ Empty1 &accessE1(FieldOverlap &fo) { return fo.e1; }
|
|||
// CHECK: %[[RET:.*]] = bitcast i8* %[[ADJUSTED]] to %[[E1]]*
|
||||
// CHECK: ret %[[E1]]* %[[RET]]
|
||||
Empty1 &accessE2(FieldOverlap &fo) { return fo.e2; }
|
||||
|
||||
struct LaterDeclaredFieldHasLowerOffset {
|
||||
int a;
|
||||
int b;
|
||||
[[no_unique_address]] Empty1 e;
|
||||
};
|
||||
// CHECK-OPT-LABEL: @_Z41loadWhereLaterDeclaredFieldHasLowerOffset
|
||||
int loadWhereLaterDeclaredFieldHasLowerOffset(LaterDeclaredFieldHasLowerOffset &a) {
|
||||
// CHECK-OPT: getelementptr
|
||||
// CHECK-OPT: load {{.*}}, !tbaa ![[TBAA_AB:[0-9]*]]
|
||||
return a.b;
|
||||
}
|
||||
// Note, never emit TBAA for zero-size fields.
|
||||
// CHECK-OPT: ![[TBAA_AB]] = !{![[TBAA_A:[0-9]*]], ![[TBAA_INT:[0-9]*]], i64 4}
|
||||
// CHECK-OPT: ![[TBAA_A]] = !{!"_ZTS32LaterDeclaredFieldHasLowerOffset", ![[TBAA_INT]], i64 0, ![[TBAA_INT]], i64 4}
|
||||
|
|
Loading…
Reference in New Issue