[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