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

Lauro Ramos Venancio lauro.venancio at gmail.com
Wed Mar 21 13:52:03 PDT 2007


Something in this patch broke the llvm-gcc compilation on arm-linux:

 /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
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: unwind-arm.tar.bz2
Type: application/x-bzip2
Size: 8023 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20070321/1319a4ff/attachment.bin>


More information about the llvm-commits mailing list