summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen/packed-nest-unpacked.c
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2015-07-10 17:30:00 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2015-07-10 17:30:00 +0000
commit03ce2a16bfb31df14ae3bfb6d288e785ffe13d35 (patch)
treeb9dc3366e3a4b210306aefacf9270e56b476a1a2 /clang/test/CodeGen/packed-nest-unpacked.c
parent9b82de78fdf2434fc83391f5a47099e80db7daa3 (diff)
downloadbcm5719-llvm-03ce2a16bfb31df14ae3bfb6d288e785ffe13d35.tar.gz
bcm5719-llvm-03ce2a16bfb31df14ae3bfb6d288e785ffe13d35.zip
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
Diffstat (limited to 'clang/test/CodeGen/packed-nest-unpacked.c')
-rw-r--r--clang/test/CodeGen/packed-nest-unpacked.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/clang/test/CodeGen/packed-nest-unpacked.c b/clang/test/CodeGen/packed-nest-unpacked.c
index 1dcd2ec468d..e2bbd41a9da 100644
--- a/clang/test/CodeGen/packed-nest-unpacked.c
+++ b/clang/test/CodeGen/packed-nest-unpacked.c
@@ -60,6 +60,35 @@ 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
+ // CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1
return gbitfield.y.b2;
}
+
+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;
+}
+
OpenPOWER on IntegriCloud