[llvm-commits] [125160] Better support for variable size struct fields.

dpatel at apple.com dpatel at apple.com
Mon Mar 19 13:55:02 PDT 2007


Revision: 125160
Author:   dpatel
Date:     2007-03-19 13:55:02 -0700 (Mon, 19 Mar 2007)

Log Message:
-----------
Better support for variable size struct fields.
Patch by Duncan Sands.

Modified Paths:
--------------
    apple-local/branches/llvm/gcc/llvm-convert.cpp
    apple-local/branches/llvm/gcc/llvm-types.cpp

Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-convert.cpp	2007-03-19 19:06:59 UTC (rev 125159)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp	2007-03-19 20:55:02 UTC (rev 125160)
@@ -4660,12 +4660,6 @@
     assert(DECL_LLVM_SET_P(FieldDecl) && "Struct not laid out for LLVM?");
     ConstantInt *CI = cast<ConstantInt>(DECL_LLVM(FieldDecl));
     uint32_t MemberIndex = CI->getZExtValue();
-    if (MemberIndex == ~0U) {
-      assert(isStructWithVarSizeArrayAtEnd(StructTy) &&
-             "Isn't var sized array access!");
-      CI = ConstantInt::get(Type::Int32Ty, StructTy->getNumContainedTypes()-1);
-      MemberIndex = CI->getZExtValue();
-    }
     assert(MemberIndex < StructTy->getNumContainedTypes() &&
            "Field Idx out of range!");
     FieldPtr = new GetElementPtrInst(StructAddrLV.Ptr,
@@ -5476,35 +5470,32 @@
       // If not, things are much simpler.
       assert(DECL_LLVM_SET_P(Field) && "Struct not laid out for LLVM?");
       unsigned FieldNo = cast<ConstantInt>(DECL_LLVM(Field))->getZExtValue();
-      
+      assert(FieldNo < ResultElts.size() && "Invalid struct field number!");
+
+      // Example: struct X { int A; char C[]; } x = { 4, "foo" };
+      assert(TYPE_SIZE(TREE_TYPE(Field)) ||
+             (FieldNo == ResultElts.size()-1 &&
+              isStructWithVarSizeArrayAtEnd(STy))
+             && "field with no size is not array at end of struct!");
+
       // If this is an initialization of a global that ends with a variable
       // sized array at its end, and the initializer has a non-zero number of
-      // elements, we must handle this case now.  In this case, FieldNo is ~0U
-      // and Val contains the actual type for the array.  
-      if (FieldNo == ~0U) {
-        // Handle: struct X { int A; char C[]; } x = { 4, "foo" };
-        assert(isStructWithVarSizeArrayAtEnd(STy) &&
-               "Struct doesn't end with variable sized array!");
-        FieldNo = STy->getNumElements()-1;
-        ResultElts[FieldNo] = Val;
-      } else {
-        assert(FieldNo < ResultElts.size() && "Invalid struct field number!");
-
-        // Otherwise, we know that the initializer has to match the element type
-        // of the LLVM structure field.  If not, then there is something that is
-        // not straight-forward going on.  For example, we could be initializing
-        // an unaligned integer field (e.g. due to attribute packed) with an 
-        // 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 (Val->getType() != STy->getElementType(FieldNo))
-          Val = ConvertStructFieldInitializerToType(Val, 
+      // elements, then Val contains the actual type for the array.  Otherwise,
+      // we know that the initializer has to match the element type of the LLVM
+      // structure field.  If not, then there is something that is not
+      // straight-forward going on.  For example, we could be initializing an
+      // unaligned integer field (e.g. due to attribute packed) with an
+      // 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)) &&
+          Val->getType() != STy->getElementType(FieldNo))
+        Val = ConvertStructFieldInitializerToType(Val,
                                                   STy->getElementType(FieldNo));
 
-        ResultElts[FieldNo] = Val;
-      }
+      ResultElts[FieldNo] = Val;
     }
-    
+
     NextField = TREE_CHAIN(Field);
   }
   
@@ -5716,31 +5707,18 @@
     ConstantInt *CI = cast<ConstantInt>(DECL_LLVM(FieldDecl));
     uint64_t MemberIndex = CI->getZExtValue();
     
-    if (MemberIndex  != ~0U) {
-      std::vector<Value*> Idxs;
-      Idxs.push_back(Constant::getNullValue(Type::Int32Ty));
-      Idxs.push_back(CI);
-      FieldPtr = ConstantExpr::getGetElementPtr(StructAddrLV, &Idxs[0], 
-                                                Idxs.size());
-      
-      // Now that we did an offset from the start of the struct, subtract off
-      // the offset from BitStart.
-      if (MemberIndex) {
-        const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));
-        BitStart -= SL->getElementOffset(MemberIndex) * 8;
-      }
-    } else {
-      // We were unable to make a nice offset, emit an ugly one.
-      Constant *Offset = Convert(field_offset);
-      FieldPtr = ConstantExpr::getPtrToInt(StructAddrLV, Offset->getType());
-      FieldPtr = ConstantExpr::getAdd(FieldPtr, Offset);
-      FieldPtr = ConstantExpr::getIntToPtr(FieldPtr, PointerType::get(FieldTy));
-      
-      // Do horrible pointer arithmetic to get the address of the field.
-      unsigned ByteOffset = TREE_INT_CST_LOW(field_offset);
-      BitStart -= ByteOffset * 8;
-    }
+    std::vector<Value*> Idxs;
+    Idxs.push_back(Constant::getNullValue(Type::Int32Ty));
+    Idxs.push_back(CI);
+    FieldPtr = ConstantExpr::getGetElementPtr(StructAddrLV, &Idxs[0],
+                                              Idxs.size());
     
+    // Now that we did an offset from the start of the struct, subtract off
+    // the offset from BitStart.
+    if (MemberIndex) {
+      const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));
+      BitStart -= SL->getElementOffset(MemberIndex) * 8;
+    }
   } else {
     Constant *Offset = Convert(field_offset);
     Constant *Ptr = ConstantExpr::getPtrToInt(StructAddrLV, Offset->getType());

Modified: apple-local/branches/llvm/gcc/llvm-types.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-types.cpp	2007-03-19 19:06:59 UTC (rev 125159)
+++ apple-local/branches/llvm/gcc/llvm-types.cpp	2007-03-19 20:55:02 UTC (rev 125160)
@@ -962,8 +962,11 @@
       while (CurFieldNo < ElementOffsetInBytes.size() &&
              getFieldEndOffsetInBytes(CurFieldNo)*8 <= FieldOffsetInBits)
         ++CurFieldNo;
-      if (CurFieldNo >= ElementOffsetInBytes.size()) return ~0U;
-      return CurFieldNo;
+      if (CurFieldNo < ElementOffsetInBytes.size())
+        return CurFieldNo;
+      // Otherwise, we couldn't find the field!
+      assert(0 && "Could not find field!");
+      return ~0U;
     }
 
     // Handle zero sized fields now.  If the next field is zero sized, return
@@ -1009,28 +1012,15 @@
   return Result;
 }
 
-/// isNotLastField - Return true if this is not the last field in its record.
-///
-static bool isNotLastField(tree Field) {
-  for (Field = TREE_CHAIN(Field); Field; Field = TREE_CHAIN(Field))
-    if (TREE_CODE(Field) == FIELD_DECL)
-      return true;
-  return false;
-}
-
-
 /// DecodeStructFields - This method decodes the specified field, if it is a
 /// FIELD_DECL, adding or updating the specified StructTypeConversionInfo to
 /// reflect it.  
 void TypeConverter::DecodeStructFields(tree Field,
                                        StructTypeConversionInfo &Info) {
   if (TREE_CODE(Field) != FIELD_DECL ||
-      // Don't include variable sized fields, doing so would break anything
-      // after them... unless this is the last field.
-      ((TYPE_SIZE(TREE_TYPE(Field)) == 0 ||
-        TREE_CODE(TYPE_SIZE(TREE_TYPE(Field))) != INTEGER_CST) &&
-       isNotLastField(Field))) return;
-  
+      TREE_CODE(DECL_FIELD_OFFSET(Field)) != INTEGER_CST)
+    return;
+
   // Handle bit-fields specially.
   if (DECL_BIT_FIELD_TYPE(Field)) {
     DecodeStructBitField(Field, Info);
@@ -1218,12 +1208,8 @@
   // variable offset.
   unsigned CurFieldNo = 0;
   for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
-    if (TREE_CODE(Field) == FIELD_DECL) {
-      // If this field comes after a variable sized element, stop trying to
-      // assign DECL_LLVM's.
-      if (TREE_CODE(DECL_FIELD_OFFSET(Field)) != INTEGER_CST)
-        break;
-      
+    if (TREE_CODE(Field) == FIELD_DECL &&
+        TREE_CODE(DECL_FIELD_OFFSET(Field)) == INTEGER_CST) {
       unsigned FieldOffsetInBits = getFieldOffsetInBits(Field);
       tree FieldType = TREE_TYPE(Field);
       
@@ -1241,10 +1227,9 @@
       
       // 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) && TREE_CODE(TYPE_SIZE(FieldType)) == INTEGER_CST&&
-        TREE_INT_CST_LOW(TYPE_SIZE(FieldType)) == 0;
-        
+      bool isZeroSizeField = !TYPE_SIZE(FieldType) ||
+        integer_zerop(TYPE_SIZE(FieldType));
+
       unsigned FieldNo = 
         Info.getLLVMFieldFor(FieldOffsetInBits, CurFieldNo, isZeroSizeField);
       SET_DECL_LLVM(Field, ConstantInt::get(Type::Int32Ty, FieldNo));





More information about the llvm-commits mailing list