[llvm-commits] [dragonegg] r163470 - in /dragonegg/trunk: include/dragonegg/Trees.h src/Convert.cpp src/Trees.cpp test/validator/c/2012-09-08-BitfieldAlignment.c

Duncan Sands baldrick at free.fr
Sat Sep 8 06:20:55 PDT 2012


Author: baldrick
Date: Sat Sep  8 08:20:54 2012
New Revision: 163470

URL: http://llvm.org/viewvc/llvm-project?rev=163470&view=rev
Log:
Correctly compute the alignment of struct fields, in particular bitfields:
DECL_ALIGN doesn't return the alignment of the octet containing the first
bit of the field, which is what we currently need.  This should fix the
gcc-4.7 buildbot, which is crashing due to the use of movaps to store to
a memory location that the front-end wrongly claimed was 16 byte aligned.

Added:
    dragonegg/trunk/test/validator/c/2012-09-08-BitfieldAlignment.c
Modified:
    dragonegg/trunk/include/dragonegg/Trees.h
    dragonegg/trunk/src/Convert.cpp
    dragonegg/trunk/src/Trees.cpp

Modified: dragonegg/trunk/include/dragonegg/Trees.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Trees.h?rev=163470&r1=163469&r2=163470&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/Trees.h (original)
+++ dragonegg/trunk/include/dragonegg/Trees.h Sat Sep  8 08:20:54 2012
@@ -122,6 +122,10 @@
 /// getFieldOffsetInBits - Return the bit offset of a FIELD_DECL in a structure.
 uint64_t getFieldOffsetInBits(const_tree field);
 
+/// getFieldAlignment - Return (in octets) the alignment within a structure of
+/// the octet containing the first bit of the given FIELD_DECL.
+unsigned getFieldAlignment(const_tree field);
+
 /// isBitfield - Returns whether to treat the specified field as a bitfield.
 bool isBitfield(const_tree field_decl);
 

Modified: dragonegg/trunk/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=163470&r1=163469&r2=163470&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Sat Sep  8 08:20:54 2012
@@ -2012,8 +2012,8 @@
       unsigned DestFieldAlign = DestLoc.getAlignment();
       unsigned SrcFieldAlign = SrcLoc.getAlignment();
       if (FieldIdx) {
-        DestFieldAlign = MinAlign(DestFieldAlign, DECL_ALIGN(Field) / 8);
-        SrcFieldAlign = MinAlign(SrcFieldAlign, DECL_ALIGN(Field) / 8);
+        DestFieldAlign = MinAlign(DestFieldAlign, getFieldAlignment(Field));
+        SrcFieldAlign = MinAlign(SrcFieldAlign, getFieldAlignment(Field));
       }
 
       // Copy the field.
@@ -2108,7 +2108,7 @@
       // Compute the field's alignment.
       unsigned FieldAlign = DestLoc.getAlignment();
       if (FieldIdx)
-        FieldAlign = MinAlign(FieldAlign, DECL_ALIGN(Field) / 8);
+        FieldAlign = MinAlign(FieldAlign, getFieldAlignment(Field));
 
       // Zero the field.
       MemRef FieldLoc(FieldPtr, FieldAlign, DestLoc.Volatile);
@@ -6069,6 +6069,7 @@
 
   // BitStart - This is the actual offset of the field from the start of the
   // struct, in bits.  For bitfields this may be on a non-byte boundary.
+  uint64_t FieldBitOffset = getInt64(DECL_FIELD_BIT_OFFSET(FieldDecl), true);
   unsigned BitStart;
   Value *FieldPtr;
 
@@ -6079,8 +6080,7 @@
     // Get a pointer to the byte in which the GCC field starts.
     FieldPtr = Builder.CreateStructGEP(StructAddrLV.Ptr, MemberIndex);
     // Within that byte, the bit at which the GCC field starts.
-    BitStart = TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(TREE_OPERAND(exp, 1)));
-    BitStart &= 7;
+    BitStart = FieldBitOffset & 7;
   } else {
     // Offset will hold the field offset in octets.
     Value *Offset;
@@ -6105,7 +6105,7 @@
     }
 
     // Here BitStart gives the offset of the field in bits from Offset.
-    BitStart = getInt64(DECL_FIELD_BIT_OFFSET(FieldDecl), true);
+    BitStart = FieldBitOffset;
 
     // Incorporate as much of it as possible into the pointer computation.
     unsigned ByteOffset = BitStart / 8;
@@ -6121,9 +6121,9 @@
     FieldPtr = Builder.CreateBitCast(FieldPtr, FieldTy->getPointerTo());
   }
 
-  // The alignment is given by DECL_ALIGN.  Be conservative and don't assume
-  // that the field is properly aligned even if the type is not.
-  LVAlign = MinAlign(LVAlign, DECL_ALIGN(FieldDecl) / 8);
+  // Compute the alignment of the octet containing the first bit of the field,
+  // without assuming that the containing struct itself is properly aligned.
+  LVAlign = MinAlign(LVAlign, getFieldAlignment(FieldDecl));
 
   // If the FIELD_DECL has an annotate attribute on it, emit it.
   if (lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl)))

Modified: dragonegg/trunk/src/Trees.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Trees.cpp?rev=163470&r1=163469&r2=163470&view=diff
==============================================================================
--- dragonegg/trunk/src/Trees.cpp (original)
+++ dragonegg/trunk/src/Trees.cpp Sat Sep  8 08:20:54 2012
@@ -223,6 +223,18 @@
   return Result;
 }
 
+/// getFieldAlignment - Return (in octets) the alignment within a structure of
+/// the octet containing the first bit of the given FIELD_DECL.
+unsigned getFieldAlignment(const_tree field) {
+  // DECL_OFFSET_ALIGN is the maximum power-of-two that is known to divide
+  // DECL_FIELD_OFFSET*BITS_PER_UNIT.  The field itself is offset a further
+  // DECL_FIELD_BIT_OFFSET bits.
+  assert(DECL_OFFSET_ALIGN(field) > 0 && (DECL_OFFSET_ALIGN(field) & 7) == 0 &&
+         "Field has no or wrong alignment!");
+  uint64_t FieldBitOffset = getInt64(DECL_FIELD_BIT_OFFSET(field), true);
+  return MinAlign(DECL_OFFSET_ALIGN(field) / 8, FieldBitOffset / 8);
+}
+
 /// isBitfield - Returns whether to treat the specified field as a bitfield.
 bool isBitfield(const_tree field_decl) {
   if (!DECL_BIT_FIELD(field_decl))

Added: dragonegg/trunk/test/validator/c/2012-09-08-BitfieldAlignment.c
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/test/validator/c/2012-09-08-BitfieldAlignment.c?rev=163470&view=auto
==============================================================================
--- dragonegg/trunk/test/validator/c/2012-09-08-BitfieldAlignment.c (added)
+++ dragonegg/trunk/test/validator/c/2012-09-08-BitfieldAlignment.c Sat Sep  8 08:20:54 2012
@@ -0,0 +1,41 @@
+// RUN: %dragonegg -S %s -o - | FileCheck %s
+// Check that bitfields are aligned properly.
+
+struct __attribute__ ((__packed__)) __attribute__ ((aligned (4))) Foo {
+    int aligned;
+    unsigned char aligned4_a : 3;
+    unsigned char aligned4_b : 3;
+    unsigned char aligned4_c : 3;
+    unsigned char aligned1_a : 3;
+    unsigned char aligned1_b : 3;
+    unsigned char aligned1_c : 3;
+    unsigned char aligned2 : 3;
+};
+
+extern void baz(struct Foo *);
+
+void bar() {
+  struct Foo foo;
+  foo.aligned4_a = 7;
+// CHECK: load i8* {{.*}}, align 4
+// CHECK: store i8 {{.*}}, align 4
+  foo.aligned4_b = 7;
+// CHECK: load i8* {{.*}}, align 4
+// CHECK: store i8 {{.*}}, align 4
+  foo.aligned4_c = 7;
+// CHECK: load i16* {{.*}}, align 4
+// CHECK: store i16 {{.*}}, align 4
+  foo.aligned1_a = 7;
+// CHECK: load i8* {{.*}}, align 1
+// CHECK: store i8 {{.*}}, align 1
+  foo.aligned1_b = 7;
+// CHECK: load i8* {{.*}}, align 1
+// CHECK: store i8 {{.*}}, align 1
+  foo.aligned1_c = 7;
+// CHECK: load i16* {{.*}}, align 1
+// CHECK: store i16 {{.*}}, align 1
+  foo.aligned2 = 7;
+// CHECK: load i8* {{.*}}, align 2
+// CHECK: store i8 {{.*}}, align 2
+  baz(&foo);
+}





More information about the llvm-commits mailing list