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

Chris Lattner clattner at apple.com
Sat Mar 24 16:49:01 PDT 2007


On Mar 21, 2007, at 1:52 PM, Lauro Ramos Venancio wrote:
> Something in this patch broke the llvm-gcc compilation on arm-linux:

Is this already fixed?

If not, Duncan, can you please investigate?  Lauro, can you try to  
reduce a .i file?

Thanks,

-Chris

> /home/laurov/llvm/llvm-gcc/build/gcc/xgcc
> -B/home/laurov/llvm/llvm-gcc/build/gcc/
> -B/usr/local/arm-linux-gnueabi/bin/
> -B/usr/local/arm-linux-gnueabi/lib/ -isystem
> /usr/local/arm-linux-gnueabi/include -isystem
> /usr/local/arm-linux-gnueabi/sys-include -O2  -DIN_GCC    -W -Wall
> -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
> -Wold-style-definition  -isystem ./include  -fPIC -g
> -DHAVE_GTHR_DEFAULT -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED  -I. -I.
> -I/home/laurov/llvm/llvm-gcc/gcc -I/home/laurov/llvm/llvm-gcc/gcc/.
> -I/home/laurov/llvm/llvm-gcc/gcc/../include
> -I/home/laurov/llvm/llvm-gcc/gcc/../libcpp/include
> -I/home/laurov/llvm/llvm/include
> -I/home/laurov/llvm/llvm/build//include -fexceptions  -c
> /home/laurov/llvm/llvm-gcc/gcc/config/arm/unwind-arm.c -o
> libgcc/./unwind-arm.o
> cc1: /home/laurov/llvm/llvm-gcc/gcc/llvm-types.cpp:968: unsigned int
> StructTypeConversionInfo::getLLVMFieldFor(uint64_t, unsigned int&,
> bool): Assertion `0 && "Could not find field!"' failed.
> /home/laurov/llvm/llvm-gcc/gcc/config/arm/unwind-arm.c: In function
> '_Unwind_Complete':
> /home/laurov/llvm/llvm-gcc/gcc/config/arm/unwind-arm.c:582: internal
> compiler error: Aborted
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <URL:http://llvm.org/bugs> for instructions.
> make[2]: *** [libgcc/./unwind-arm.o] Error 1
>
>
>
> This bug can be reproduced using llvm-gcc for i386:
>
> laurov at edgy-laptop:/tmp$ llvm-gcc unwind-arm.c
> cc1: ../../gcc/llvm-types.cpp:968: unsigned int
> StructTypeConversionInfo::getLLVMFieldFor(uint64_t, unsigned int&,
> bool): Assertion `0 && "Could not find field!"' failed.
> unwind-arm.c: In function 'get_eit_entry':
> unwind-arm.c:382: internal compiler error: Aborted
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <URL:http://llvm.org/bugs> for instructions.
>
> Lauro
>
>
> 2007/3/19, dpatel at apple.com <dpatel at apple.com>:
>> 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));
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>> <unwind-arm.tar.bz2>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list