[llvm-commits] [llvm-gcc-4.2] r45590 - in /llvm-gcc-4.2/trunk/gcc: llvm-abi.h llvm-convert.cpp llvm-debug.cpp llvm-internal.h llvm-types.cpp

Duncan Sands baldrick at free.fr
Fri Jan 4 10:09:09 PST 2008


Author: baldrick
Date: Fri Jan  4 12:09:09 2008
New Revision: 45590

URL: http://llvm.org/viewvc/llvm-project?rev=45590&view=rev
Log:
If a struct field is marked as a bitfield but
didn't need to be, treat it like an ordinary
field.  The Ada front-end likes to mark fields
as bitfields preemptively, so this can occur
quite often for Ada.  What is more, it can
mark non-integer fields as bitfields.  In all
examples I came across so far, these non-integer
bitfields can be treated like ordinary fields.
With this patch, the Ada front-end builds (but
does not bootstrap)!  It is true that the problem
of non-integer bitfields could be handled in the
Ada front-end, but since ignoring silly bitfields
seems like a good idea for all front-ends I chose
to solve it in the generic code.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-abi.h
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-internal.h
    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp

Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=45590&r1=45589&r2=45590&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Fri Jan  4 12:09:09 2008
@@ -106,7 +106,7 @@
     for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
       if (TREE_CODE(Field) == FIELD_DECL) {
         if (!FoundField)
-          FoundField = TREE_TYPE(Field);
+          FoundField = getDeclaredType(Field);
         else
           return 0;   // More than one field.
       }
@@ -206,9 +206,9 @@
         if (TREE_CODE(Field) == FIELD_DECL) {
           unsigned FNo = GetFieldIndex(Field);
           assert(FNo != ~0U && "Case not handled yet!");
-          
+
           C.EnterField(FNo, Ty);
-          HandleArgument(TREE_TYPE(Field));
+          HandleArgument(getDeclaredType(Field));
           C.ExitField();
         }
     } else if (TREE_CODE(type) == COMPLEX_TYPE) {

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=45590&r1=45589&r2=45590&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Fri Jan  4 12:09:09 2008
@@ -5071,8 +5071,8 @@
 
   StructAddrLV.Ptr = BitCastToType(StructAddrLV.Ptr,
                                    PointerType::getUnqual(StructTy));
-  const Type *FieldTy = ConvertType(TREE_TYPE(FieldDecl));
-  
+  const Type *FieldTy = ConvertType(getDeclaredType(FieldDecl));
+
   // 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.
   unsigned BitStart = getComponentRefOffsetInBits(exp);
@@ -5114,7 +5114,7 @@
                           PointerType::getUnqual(FieldTy));
   }
 
-  if (tree DeclaredType = DECL_BIT_FIELD_TYPE(FieldDecl)) {
+  if (isBitfield(FieldDecl)) {
     assert(DECL_SIZE(FieldDecl) &&
            TREE_CODE(DECL_SIZE(FieldDecl)) == INTEGER_CST &&
            "Variable sized bitfield?");
@@ -5124,7 +5124,6 @@
       cast<PointerType>(FieldPtr->getType())->getElementType();
 
     // If this is a bitfield, the declared type must be an integral type.
-    FieldTy = ConvertType(DeclaredType);
     // If the field result is a bool, cast to a ubyte instead.  It is not
     // possible to access all bits of a memory object with a bool (only the low
     // bit) but it is possible to access them with a byte.
@@ -5970,7 +5969,7 @@
 
     // If the field is a bitfield, it could be spread across multiple fields and
     // may start at some bit offset.
-    if (DECL_BIT_FIELD_TYPE(Field)) {
+    if (isBitfield(Field)) {
       ProcessBitFieldInitialization(Field, Val, STy, ResultElts);
     } else {
       // If not, things are much simpler.
@@ -5978,7 +5977,7 @@
       assert(FieldNo < ResultElts.size() && "Invalid struct field number!");
 
       // Example: struct X { int A; char C[]; } x = { 4, "foo" };
-      assert(TYPE_SIZE(TREE_TYPE(Field)) ||
+      assert(TYPE_SIZE(getDeclaredType(Field)) ||
              (FieldNo == ResultElts.size()-1 &&
               isStructWithVarSizeArrayAtEnd(STy))
              && "field with no size is not array at end of struct!");
@@ -5993,7 +5992,7 @@
       // integer.  The struct field will have type [4 x ubyte] instead of
       // "int" for example.  If we ignored this, we would lay out the
       // initializer wrong.
-      if (TYPE_SIZE(TREE_TYPE(Field)) &&
+      if (TYPE_SIZE(getDeclaredType(Field)) &&
           Val->getType() != STy->getElementType(FieldNo))
         Val = ConvertStructFieldInitializerToType(Val,
                                                   STy->getElementType(FieldNo));
@@ -6220,7 +6219,7 @@
   
   StructAddrLV = ConstantExpr::getBitCast(StructAddrLV,
                                           PointerType::getUnqual(StructTy));
-  const Type *FieldTy = ConvertType(TREE_TYPE(FieldDecl));
+  const Type *FieldTy = ConvertType(getDeclaredType(FieldDecl));
   
   // 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.
@@ -6253,12 +6252,10 @@
     FieldPtr = ConstantExpr::getIntToPtr(Ptr, PointerType::getUnqual(FieldTy));
   }
   
-  if (DECL_BIT_FIELD_TYPE(FieldDecl)) {
-    FieldTy = ConvertType(DECL_BIT_FIELD_TYPE(FieldDecl));
+  if (isBitfield(FieldDecl))
     FieldPtr = ConstantExpr::getBitCast(FieldPtr, 
                                         PointerType::getUnqual(FieldTy));
-  }
-  
+
   assert(BitStart == 0 &&
          "It's a bitfield reference or we didn't get to the field!");
   return FieldPtr;

Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=45590&r1=45589&r2=45590&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Fri Jan  4 12:09:09 2008
@@ -119,12 +119,7 @@
 ///
 static tree FieldType(tree Field) {
   if (TREE_CODE (Field) == ERROR_MARK) return integer_type_node;
-
-  tree type = DECL_BIT_FIELD_TYPE (Field);
-  if (type == NULL_TREE)
-    type = TREE_TYPE (Field);
-
-  return type;
+  return getDeclaredType(Field);
 }
 
 /// GetNodeName - Returns the name stored in a node regardless of whether the

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=45590&r1=45589&r2=45590&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Fri Jan  4 12:09:09 2008
@@ -216,6 +216,13 @@
 /// corresponds to an LLVM array type.
 bool isArrayCompatible(tree_node *type);
 
+/// isBitfield - Returns whether to treat the specified field as a bitfield.
+bool isBitfield(tree_node *field_decl);
+
+/// getDeclaredType - Get the declared type for the specified field, and
+/// not the shrunk-to-fit type that GCC gives us in TREE_TYPE.
+tree_node *getDeclaredType(tree_node *field_decl);
+
 /// ValidateRegisterVariable - Check that a static "asm" variable is
 /// well-formed.  If not, emit error messages and return true.  If so, return
 /// false.

Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=45590&r1=45589&r2=45590&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Fri Jan  4 12:09:09 2008
@@ -328,6 +328,42 @@
     );
 }
 
+/// isBitfield - Returns whether to treat the specified field as a bitfield.
+bool isBitfield(tree_node *field_decl) {
+  tree type = DECL_BIT_FIELD_TYPE(field_decl);
+  if (!type)
+    return false;
+
+  // A bitfield.  But do we need to treat it as one?
+
+  assert(DECL_FIELD_BIT_OFFSET(field_decl) && "Bitfield with no bit offset!");
+  if (TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(field_decl)) & 7)
+    // Does not start on a byte boundary - must treat as a bitfield.
+    return true;
+
+  if (!TYPE_SIZE(type) || !isInt64(TYPE_SIZE (type), true))
+    // No size or variable sized - play safe, treat as a bitfield.
+    return true;
+
+  uint64_t TypeSizeInBits = getInt64(TYPE_SIZE (type), true);
+  assert(!(TypeSizeInBits & 7) && "A type with a non-byte size!");
+
+  assert(DECL_SIZE(field_decl) && "Bitfield with no bit size!");
+  unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(field_decl));
+  if (FieldSizeInBits < TypeSizeInBits)
+    // Not wide enough to hold the entire type - treat as a bitfield.
+    return true;
+
+  return false;
+}
+
+/// getDeclaredType - Get the declared type for the specified field_decl, and
+/// not the shrunk-to-fit type that GCC gives us in TREE_TYPE.
+tree getDeclaredType(tree_node *field_decl) {
+  return DECL_BIT_FIELD_TYPE(field_decl) ?
+    DECL_BIT_FIELD_TYPE(field_decl) : TREE_TYPE (field_decl);
+}
+
 /// refine_type_to - Cause all users of the opaque type old_type to switch
 /// to the more concrete type new_type.
 void refine_type_to(tree old_type, tree new_type)
@@ -464,6 +500,7 @@
 //                              Helper Routines
 //===----------------------------------------------------------------------===//
 
+
 /// getFieldOffsetInBits - Return the offset (in bits) of a FIELD_DECL in a
 /// structure.
 static unsigned getFieldOffsetInBits(tree Field) {
@@ -474,7 +511,6 @@
   return Result;
 }
 
-
 /// FindLLVMTypePadding - If the specified struct has any inter-element padding,
 /// add it to the Padding array.
 static void FindLLVMTypePadding(const Type *Ty, unsigned BitOffset,
@@ -619,7 +655,7 @@
         return true;
 
       unsigned FieldBitOffset = getFieldOffsetInBits(Field);
-      if (GCCTypeOverlapsWithPadding(TREE_TYPE(Field),
+      if (GCCTypeOverlapsWithPadding(getDeclaredType(Field),
                                      PadStartBits-FieldBitOffset, PadSizeBits))
         return true;
     }
@@ -1589,7 +1625,7 @@
     return;
 
   // Handle bit-fields specially.
-  if (DECL_BIT_FIELD_TYPE(Field)) {
+  if (isBitfield(Field)) {
     DecodeStructBitField(Field, Info);
     return;
   }
@@ -1600,8 +1636,8 @@
   unsigned StartOffsetInBits = getFieldOffsetInBits(Field);
   assert((StartOffsetInBits & 7) == 0 && "Non-bit-field has non-byte offset!");
   unsigned StartOffsetInBytes = StartOffsetInBits/8;
-  
-  const Type *Ty = ConvertType(TREE_TYPE(Field));
+
+  const Type *Ty = ConvertType(getDeclaredType(Field));
 
   // Pop any previous elements out of the struct if they overlap with this one.
   // This can happen when the C++ front-end overlaps fields with tail padding in
@@ -1843,24 +1879,24 @@
     if (TREE_CODE(Field) == FIELD_DECL &&
         TREE_CODE(DECL_FIELD_OFFSET(Field)) == INTEGER_CST) {
       unsigned FieldOffsetInBits = getFieldOffsetInBits(Field);
-      tree FieldType = TREE_TYPE(Field);
-      
+      tree FieldType = getDeclaredType(Field);
+
       // If this is a bitfield, we may want to adjust the FieldOffsetInBits to
       // produce safe code.  In particular, bitfields will be loaded/stored as
       // their *declared* type, not the smallest integer type that contains
       // them.  As such, we need to respect the alignment of the declared type.
-      if (tree DeclaredType = DECL_BIT_FIELD_TYPE(Field)) {
+      if (isBitfield(Field)) {
         // If this is a bitfield, the declared type must be an integral type.
-        const Type *DeclFieldTy = ConvertType(DeclaredType);
-        unsigned DeclBitAlignment = Info->getTypeAlignment(DeclFieldTy)*8;
-        
-        FieldOffsetInBits &= ~(DeclBitAlignment-1ULL);
+        const Type *FieldTy = ConvertType(FieldType);
+        unsigned BitAlignment = Info->getTypeAlignment(FieldTy)*8;
+
+        FieldOffsetInBits &= ~(BitAlignment-1ULL);
         // When we fix the field alignment, we must restart the FieldNo search
         // because the FieldOffsetInBits can be lower than it was in the
         // previous iteration.
         CurFieldNo = 0;
       }
-      
+
       // Figure out if this field is zero bits wide, e.g. {} or [0 x int].  Do
       // not include variable sized fields here.
       bool isZeroSizeField = !TYPE_SIZE(FieldType) ||





More information about the llvm-commits mailing list