Author: baldrick Date: Fri Jan 4 12:09:09 2008 New Revision: 45590 URL: http://llvm.org/viewvc/llvm-project?rev=45590&view=rev Log: If a struct field is marked as a bitfield but didn't need to be, treat it like an ordinary field. The Ada front-end likes to mark fields as bitfields preemptively, so this can occur quite often for Ada. What is more, it can mark non-integer fields as bitfields. In all examples I came across so far, these non-integer bitfields can be treated like ordinary fields. With this patch, the Ada front-end builds (but does not bootstrap)! It is true that the problem of non-integer bitfields could be handled in the Ada front-end, but since ignoring silly bitfields seems like a good idea for all front-ends I chose to solve it in the generic code.
Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp llvm-gcc-4.2/trunk/gcc/llvm-internal.h llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=45590&r1=45589&r2=45590&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Fri Jan 4 12:09:09 2008 @@ -106,7 +106,7 @@ for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) if (TREE_CODE(Field) == FIELD_DECL) { if (!FoundField) - FoundField = TREE_TYPE(Field); + FoundField = getDeclaredType(Field); else return 0; // More than one field. } @@ -206,9 +206,9 @@ if (TREE_CODE(Field) == FIELD_DECL) { unsigned FNo = GetFieldIndex(Field); assert(FNo != ~0U && "Case not handled yet!"); - + C.EnterField(FNo, Ty); - HandleArgument(TREE_TYPE(Field)); + HandleArgument(getDeclaredType(Field)); C.ExitField(); } } else if (TREE_CODE(type) == COMPLEX_TYPE) { Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=45590&r1=45589&r2=45590&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Fri Jan 4 12:09:09 2008 @@ -5071,8 +5071,8 @@ StructAddrLV.Ptr = BitCastToType(StructAddrLV.Ptr, PointerType::getUnqual(StructTy)); - const Type *FieldTy = ConvertType(TREE_TYPE(FieldDecl)); - + const Type *FieldTy = ConvertType(getDeclaredType(FieldDecl)); + // BitStart - This is the actual offset of the field from the start of the // struct, in bits. For bitfields this may be on a non-byte boundary. unsigned BitStart = getComponentRefOffsetInBits(exp); @@ -5114,7 +5114,7 @@ PointerType::getUnqual(FieldTy)); } - if (tree DeclaredType = DECL_BIT_FIELD_TYPE(FieldDecl)) { + if (isBitfield(FieldDecl)) { assert(DECL_SIZE(FieldDecl) && TREE_CODE(DECL_SIZE(FieldDecl)) == INTEGER_CST && "Variable sized bitfield?"); @@ -5124,7 +5124,6 @@ cast<PointerType>(FieldPtr->getType())->getElementType(); // If this is a bitfield, the declared type must be an integral type. - FieldTy = ConvertType(DeclaredType); // If the field result is a bool, cast to a ubyte instead. It is not // possible to access all bits of a memory object with a bool (only the low // bit) but it is possible to access them with a byte. @@ -5970,7 +5969,7 @@ // If the field is a bitfield, it could be spread across multiple fields and // may start at some bit offset. - if (DECL_BIT_FIELD_TYPE(Field)) { + if (isBitfield(Field)) { ProcessBitFieldInitialization(Field, Val, STy, ResultElts); } else { // If not, things are much simpler. @@ -5978,7 +5977,7 @@ assert(FieldNo < ResultElts.size() && "Invalid struct field number!"); // Example: struct X { int A; char C[]; } x = { 4, "foo" }; - assert(TYPE_SIZE(TREE_TYPE(Field)) || + assert(TYPE_SIZE(getDeclaredType(Field)) || (FieldNo == ResultElts.size()-1 && isStructWithVarSizeArrayAtEnd(STy)) && "field with no size is not array at end of struct!"); @@ -5993,7 +5992,7 @@ // 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)) && + if (TYPE_SIZE(getDeclaredType(Field)) && Val->getType() != STy->getElementType(FieldNo)) Val = ConvertStructFieldInitializerToType(Val, STy->getElementType(FieldNo)); @@ -6220,7 +6219,7 @@ StructAddrLV = ConstantExpr::getBitCast(StructAddrLV, PointerType::getUnqual(StructTy)); - const Type *FieldTy = ConvertType(TREE_TYPE(FieldDecl)); + const Type *FieldTy = ConvertType(getDeclaredType(FieldDecl)); // BitStart - This is the actual offset of the field from the start of the // struct, in bits. For bitfields this may be on a non-byte boundary. @@ -6253,12 +6252,10 @@ FieldPtr = ConstantExpr::getIntToPtr(Ptr, PointerType::getUnqual(FieldTy)); } - if (DECL_BIT_FIELD_TYPE(FieldDecl)) { - FieldTy = ConvertType(DECL_BIT_FIELD_TYPE(FieldDecl)); + if (isBitfield(FieldDecl)) FieldPtr = ConstantExpr::getBitCast(FieldPtr, PointerType::getUnqual(FieldTy)); - } - + assert(BitStart == 0 && "It's a bitfield reference or we didn't get to the field!"); return FieldPtr; Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=45590&r1=45589&r2=45590&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Fri Jan 4 12:09:09 2008 @@ -119,12 +119,7 @@ /// static tree FieldType(tree Field) { if (TREE_CODE (Field) == ERROR_MARK) return integer_type_node; - - tree type = DECL_BIT_FIELD_TYPE (Field); - if (type == NULL_TREE) - type = TREE_TYPE (Field); - - return type; + return getDeclaredType(Field); } /// GetNodeName - Returns the name stored in a node regardless of whether the Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=45590&r1=45589&r2=45590&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Fri Jan 4 12:09:09 2008 @@ -216,6 +216,13 @@ /// corresponds to an LLVM array type. bool isArrayCompatible(tree_node *type); +/// isBitfield - Returns whether to treat the specified field as a bitfield. +bool isBitfield(tree_node *field_decl); + +/// getDeclaredType - Get the declared type for the specified field, and +/// not the shrunk-to-fit type that GCC gives us in TREE_TYPE. +tree_node *getDeclaredType(tree_node *field_decl); + /// ValidateRegisterVariable - Check that a static "asm" variable is /// well-formed. If not, emit error messages and return true. If so, return /// false. Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=45590&r1=45589&r2=45590&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Fri Jan 4 12:09:09 2008 @@ -328,6 +328,42 @@ ); } +/// isBitfield - Returns whether to treat the specified field as a bitfield. +bool isBitfield(tree_node *field_decl) { + tree type = DECL_BIT_FIELD_TYPE(field_decl); + if (!type) + return false; + + // A bitfield. But do we need to treat it as one? + + assert(DECL_FIELD_BIT_OFFSET(field_decl) && "Bitfield with no bit offset!"); + if (TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(field_decl)) & 7) + // Does not start on a byte boundary - must treat as a bitfield. + return true; + + if (!TYPE_SIZE(type) || !isInt64(TYPE_SIZE (type), true)) + // No size or variable sized - play safe, treat as a bitfield. + return true; + + uint64_t TypeSizeInBits = getInt64(TYPE_SIZE (type), true); + assert(!(TypeSizeInBits & 7) && "A type with a non-byte size!"); + + assert(DECL_SIZE(field_decl) && "Bitfield with no bit size!"); + unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(field_decl)); + if (FieldSizeInBits < TypeSizeInBits) + // Not wide enough to hold the entire type - treat as a bitfield. + return true; + + return false; +} + +/// getDeclaredType - Get the declared type for the specified field_decl, and +/// not the shrunk-to-fit type that GCC gives us in TREE_TYPE. +tree getDeclaredType(tree_node *field_decl) { + return DECL_BIT_FIELD_TYPE(field_decl) ? + DECL_BIT_FIELD_TYPE(field_decl) : TREE_TYPE (field_decl); +} + /// refine_type_to - Cause all users of the opaque type old_type to switch /// to the more concrete type new_type. void refine_type_to(tree old_type, tree new_type) @@ -464,6 +500,7 @@ // Helper Routines //===----------------------------------------------------------------------===// + /// getFieldOffsetInBits - Return the offset (in bits) of a FIELD_DECL in a /// structure. static unsigned getFieldOffsetInBits(tree Field) { @@ -474,7 +511,6 @@ return Result; } - /// FindLLVMTypePadding - If the specified struct has any inter-element padding, /// add it to the Padding array. static void FindLLVMTypePadding(const Type *Ty, unsigned BitOffset, @@ -619,7 +655,7 @@ return true; unsigned FieldBitOffset = getFieldOffsetInBits(Field); - if (GCCTypeOverlapsWithPadding(TREE_TYPE(Field), + if (GCCTypeOverlapsWithPadding(getDeclaredType(Field), PadStartBits-FieldBitOffset, PadSizeBits)) return true; } @@ -1589,7 +1625,7 @@ return; // Handle bit-fields specially. - if (DECL_BIT_FIELD_TYPE(Field)) { + if (isBitfield(Field)) { DecodeStructBitField(Field, Info); return; } @@ -1600,8 +1636,8 @@ unsigned StartOffsetInBits = getFieldOffsetInBits(Field); assert((StartOffsetInBits & 7) == 0 && "Non-bit-field has non-byte offset!"); unsigned StartOffsetInBytes = StartOffsetInBits/8; - - const Type *Ty = ConvertType(TREE_TYPE(Field)); + + const Type *Ty = ConvertType(getDeclaredType(Field)); // Pop any previous elements out of the struct if they overlap with this one. // This can happen when the C++ front-end overlaps fields with tail padding in @@ -1843,24 +1879,24 @@ if (TREE_CODE(Field) == FIELD_DECL && TREE_CODE(DECL_FIELD_OFFSET(Field)) == INTEGER_CST) { unsigned FieldOffsetInBits = getFieldOffsetInBits(Field); - tree FieldType = TREE_TYPE(Field); - + tree FieldType = getDeclaredType(Field); + // If this is a bitfield, we may want to adjust the FieldOffsetInBits to // produce safe code. In particular, bitfields will be loaded/stored as // their *declared* type, not the smallest integer type that contains // them. As such, we need to respect the alignment of the declared type. - if (tree DeclaredType = DECL_BIT_FIELD_TYPE(Field)) { + if (isBitfield(Field)) { // If this is a bitfield, the declared type must be an integral type. - const Type *DeclFieldTy = ConvertType(DeclaredType); - unsigned DeclBitAlignment = Info->getTypeAlignment(DeclFieldTy)*8; - - FieldOffsetInBits &= ~(DeclBitAlignment-1ULL); + const Type *FieldTy = ConvertType(FieldType); + unsigned BitAlignment = Info->getTypeAlignment(FieldTy)*8; + + FieldOffsetInBits &= ~(BitAlignment-1ULL); // When we fix the field alignment, we must restart the FieldNo search // because the FieldOffsetInBits can be lower than it was in the // previous iteration. CurFieldNo = 0; } - + // 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) || _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits