]> granicus.if.org Git - clang/commitdiff
ARM/APCS ABI: Fix some problems with bit-fields in structures. After rereading
authorDaniel Dunbar <daniel@zuster.org>
Fri, 29 Jan 2010 03:22:29 +0000 (03:22 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 29 Jan 2010 03:22:29 +0000 (03:22 +0000)
the ABI spec, this turns out to simplify the code. We still have some annoying
code which mismatches the spec with regard to empty structures.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94796 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGen/arm-arguments.c

index bc512e7a276a39fe4681fdff77b5a8e0457def2e..92ff312425980abc3dc85c7039ab80e13db32018 100644 (file)
@@ -1611,30 +1611,30 @@ static bool isIntegerLikeType(QualType Ty,
        i != e; ++i, ++idx) {
     const FieldDecl *FD = *i;
 
-    // Check if this field is at offset 0.
-    uint64_t Offset = Layout.getFieldOffset(idx);
-    if (Offset != 0) {
-      // Allow padding bit-fields, but only if they are all at the end of the
-      // structure (despite the wording above, this matches gcc).
-      if (FD->isBitField() && 
-          !FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) {
-        for (; i != e; ++i)
-          if (!i->isBitField() ||
-              i->getBitWidth()->EvaluateAsInt(Context).getZExtValue())
-            return false;
-
-        // All remaining fields are padding, allow this.
-        return true;
-      }
+    // Bit-fields are not addressable, we only need to verify they are "integer
+    // like". We still have to disallow a subsequent non-bitfield, for example:
+    //   struct { int : 0; int x }
+    // is non-integer like according to gcc.
+    if (FD->isBitField()) {
+      if (!RD->isUnion())
+        HadField = true;
+
+      if (!isIntegerLikeType(FD->getType(), Context, VMContext))
+        return false;
 
-      return false;
+      continue;
     }
 
+    // Check if this field is at offset 0.
+    if (Layout.getFieldOffset(idx) != 0)
+      return false;
+
     if (!isIntegerLikeType(FD->getType(), Context, VMContext))
       return false;
     
-    // Only allow at most one field in a structure. Again this doesn't match the
-    // wording above, but follows gcc.
+    // Only allow at most one field in a structure. This doesn't match the
+    // wording above, but follows gcc in situations with a field following an
+    // empty structure.
     if (!RD->isUnion()) {
       if (HadField)
         return false;
index fb61b0f78497a3d7ce8817c1046937b2d077de38..c97c97bc581ee115f7c0e19e55cd7cf553ffdf65 100644 (file)
@@ -92,3 +92,30 @@ void f15(struct s7 a0) {}
 // APCS-GNU: define arm_apcscc void @f16()
 // AAPCS: define arm_aapcscc void @f16()
 void f16(struct s8 a0) {}
+
+// APCS-GNU: define arm_apcscc i32 @f17()
+// AAPCS: define arm_aapcscc i32 @f17()
+struct s17 { short f0 : 13; char f1 : 4; };
+struct s17 f17(void) {}
+
+// APCS-GNU: define arm_apcscc i32 @f18()
+// AAPCS: define arm_aapcscc i32 @f18()
+struct s18 { short f0; char f1 : 4; };
+struct s18 f18(void) {}
+
+// APCS-GNU: define arm_apcscc void @f19(
+// APCS-GNU: struct.s19* noalias sret
+// AAPCS: define arm_aapcscc i32 @f19()
+struct s19 { int f0; struct s8 f1; };
+struct s19 f19(void) {}
+
+// APCS-GNU: define arm_apcscc void @f20(
+// APCS-GNU: struct.s20* noalias sret
+// AAPCS: define arm_aapcscc i32 @f20()
+struct s20 { struct s8 f1; int f0; };
+struct s20 f20(void) {}
+
+// APCS-GNU: define arm_apcscc i32 @f21()
+// AAPCS: define arm_aapcscc i32 @f21()
+struct s21 { struct {} f1; int f0 : 4; };
+struct s21 f21(void) {}