[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