2011-12-06 06:23:28 +08:00
|
|
|
// RUN: %clang_cc1 %s -triple x86_64-apple-macosx10.7.2 -emit-llvm -o - | FileCheck %s
|
|
|
|
|
|
|
|
struct X { int x[6]; };
|
|
|
|
struct Y { char x[13]; struct X y; } __attribute((packed));
|
|
|
|
struct Y g;
|
|
|
|
void f(struct X);
|
2012-04-17 08:35:38 +08:00
|
|
|
struct X foo(void);
|
2011-12-06 06:23:28 +08:00
|
|
|
|
2012-04-16 11:54:45 +08:00
|
|
|
// <rdar://problem/10463337>
|
2011-12-06 06:23:28 +08:00
|
|
|
struct X test1() {
|
|
|
|
// CHECK: @test1
|
2015-11-19 13:55:59 +08:00
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
|
2011-12-06 06:23:28 +08:00
|
|
|
return g.y;
|
|
|
|
}
|
|
|
|
struct X test2() {
|
|
|
|
// CHECK: @test2
|
2015-11-19 13:55:59 +08:00
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
|
2011-12-06 06:23:28 +08:00
|
|
|
struct X a = g.y;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void test3(struct X a) {
|
|
|
|
// CHECK: @test3
|
2015-11-19 13:55:59 +08:00
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i8* {{.*}}, i64 24, i32 1, i1 false)
|
2011-12-06 06:23:28 +08:00
|
|
|
g.y = a;
|
|
|
|
}
|
|
|
|
|
2012-04-16 11:54:45 +08:00
|
|
|
// <rdar://problem/10530444>
|
2011-12-06 06:23:28 +08:00
|
|
|
void test4() {
|
|
|
|
// CHECK: @test4
|
2015-11-19 13:55:59 +08:00
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
|
2011-12-06 06:23:28 +08:00
|
|
|
f(g.y);
|
|
|
|
}
|
2012-04-16 11:54:45 +08:00
|
|
|
|
|
|
|
// PR12395
|
|
|
|
int test5() {
|
|
|
|
// CHECK: @test5
|
2015-03-14 02:21:46 +08:00
|
|
|
// CHECK: load i32, i32* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1, i32 0, i64 0), align 1
|
2012-04-16 11:54:45 +08:00
|
|
|
return g.y.x[0];
|
|
|
|
}
|
2012-04-17 08:35:38 +08:00
|
|
|
|
|
|
|
// <rdar://problem/11220251>
|
|
|
|
void test6() {
|
|
|
|
// CHECK: @test6
|
2015-11-19 13:55:59 +08:00
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y, %struct.Y* @g, i32 0, i32 1) to i8*), i8* %{{.*}}, i64 24, i32 1, i1 false)
|
2012-04-17 08:35:38 +08:00
|
|
|
g.y = foo();
|
|
|
|
}
|
2012-06-28 05:19:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
struct XBitfield {
|
|
|
|
unsigned b1 : 10;
|
|
|
|
unsigned b2 : 12;
|
|
|
|
unsigned b3 : 10;
|
|
|
|
};
|
|
|
|
struct YBitfield {
|
|
|
|
char x;
|
|
|
|
struct XBitfield y;
|
|
|
|
} __attribute((packed));
|
|
|
|
struct YBitfield gbitfield;
|
|
|
|
|
|
|
|
unsigned test7() {
|
|
|
|
// CHECK: @test7
|
Respect alignment of nested bitfields
tools/clang/test/CodeGen/packed-nest-unpacked.c contains this test:
struct XBitfield {
unsigned b1 : 10;
unsigned b2 : 12;
unsigned b3 : 10;
};
struct YBitfield {
char x;
struct XBitfield y;
} __attribute((packed));
struct YBitfield gbitfield;
unsigned test7() {
// CHECK: @test7
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 4
return gbitfield.y.b2;
}
The "align 4" is actually wrong. Accessing all of "gbitfield.y" as a single
i32 is of course possible, but that still doesn't make it 4-byte aligned as
it remains packed at offset 1 in the surrounding gbitfield object.
This alignment was changed by commit r169489, which also introduced changes
to bitfield access code in CGExpr.cpp. Code before that change used to take
into account *both* the alignment of the field to be accessed within the
current struct, *and* the alignment of that outer struct itself; this logic
was removed by the above commit.
Neglecting to consider both values can cause incorrect code to be generated
(I've seen an unaligned access crash on SystemZ due to this bug).
In order to always use the best known alignment value, this patch removes
the CGBitFieldInfo::StorageAlignment member and replaces it with a
StorageOffset member specifying the offset from the start of the surrounding
struct to the bitfield's underlying storage. This offset can then be combined
with the best-known alignment for a bitfield access lvalue to determine the
alignment to use when accessing the bitfield's storage.
Differential Revision: http://reviews.llvm.org/D11034
llvm-svn: 241916
2015-07-11 01:30:00 +08:00
|
|
|
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1
|
2012-06-28 05:19:48 +08:00
|
|
|
return gbitfield.y.b2;
|
|
|
|
}
|
Respect alignment of nested bitfields
tools/clang/test/CodeGen/packed-nest-unpacked.c contains this test:
struct XBitfield {
unsigned b1 : 10;
unsigned b2 : 12;
unsigned b3 : 10;
};
struct YBitfield {
char x;
struct XBitfield y;
} __attribute((packed));
struct YBitfield gbitfield;
unsigned test7() {
// CHECK: @test7
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 4
return gbitfield.y.b2;
}
The "align 4" is actually wrong. Accessing all of "gbitfield.y" as a single
i32 is of course possible, but that still doesn't make it 4-byte aligned as
it remains packed at offset 1 in the surrounding gbitfield object.
This alignment was changed by commit r169489, which also introduced changes
to bitfield access code in CGExpr.cpp. Code before that change used to take
into account *both* the alignment of the field to be accessed within the
current struct, *and* the alignment of that outer struct itself; this logic
was removed by the above commit.
Neglecting to consider both values can cause incorrect code to be generated
(I've seen an unaligned access crash on SystemZ due to this bug).
In order to always use the best known alignment value, this patch removes
the CGBitFieldInfo::StorageAlignment member and replaces it with a
StorageOffset member specifying the offset from the start of the surrounding
struct to the bitfield's underlying storage. This offset can then be combined
with the best-known alignment for a bitfield access lvalue to determine the
alignment to use when accessing the bitfield's storage.
Differential Revision: http://reviews.llvm.org/D11034
llvm-svn: 241916
2015-07-11 01:30:00 +08:00
|
|
|
|
|
|
|
void test8(unsigned x) {
|
|
|
|
// CHECK: @test8
|
|
|
|
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1
|
|
|
|
// CHECK: store i32 {{.*}}, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1
|
|
|
|
gbitfield.y.b2 = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct TBitfield
|
|
|
|
{
|
|
|
|
long a;
|
|
|
|
char b;
|
|
|
|
unsigned c:15;
|
|
|
|
};
|
|
|
|
struct TBitfield tbitfield;
|
|
|
|
|
|
|
|
unsigned test9() {
|
|
|
|
// CHECK: @test9
|
|
|
|
// CHECK: load i16, i16* getelementptr inbounds (%struct.TBitfield, %struct.TBitfield* @tbitfield, i32 0, i32 2), align 1
|
|
|
|
return tbitfield.c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void test10(unsigned x) {
|
|
|
|
// CHECK: @test10
|
|
|
|
// CHECK: load i16, i16* getelementptr inbounds (%struct.TBitfield, %struct.TBitfield* @tbitfield, i32 0, i32 2), align 1
|
|
|
|
// CHECK: store i16 {{.*}}, i16* getelementptr inbounds (%struct.TBitfield, %struct.TBitfield* @tbitfield, i32 0, i32 2), align 1
|
|
|
|
tbitfield.c = x;
|
|
|
|
}
|
|
|
|
|