[llvm-commits] CVS: llvm-gcc/gcc/llvm-types.c
Chris Lattner
lattner at cs.uiuc.edu
Mon Jul 25 18:17:33 PDT 2005
Changes in directory llvm-gcc/gcc:
llvm-types.c updated: 1.24 -> 1.25
---
Log message:
Fix PR449: http://llvm.cs.uiuc.edu/PR449 and PR603: http://llvm.cs.uiuc.edu/PR603 by being VERY VERY careful to match the target layout
when laying out the LLVM type for a C type. In particular, do not assume
silly things (like types always having the same alignment whenever they
are used) that hold for every target but darwin.
This fixes Regression/C++/ofstream_ctor.cpp.
---
Diffs of the changes: (+113 -74)
llvm-types.c | 187 +++++++++++++++++++++++++++++++++++------------------------
1 files changed, 113 insertions(+), 74 deletions(-)
Index: llvm-gcc/gcc/llvm-types.c
diff -u llvm-gcc/gcc/llvm-types.c:1.24 llvm-gcc/gcc/llvm-types.c:1.25
--- llvm-gcc/gcc/llvm-types.c:1.24 Fri Jul 22 13:53:38 2005
+++ llvm-gcc/gcc/llvm-types.c Mon Jul 25 20:17:22 2005
@@ -75,48 +75,30 @@
*/
static unsigned PrimitiveAlignments[OpaqueTyID];
-static unsigned getMinTargetAlignment(tree Type) {
- unsigned BasicAlignment = TYPE_ALIGN(Type);
- unsigned TestAlignment;
+static void InitializeAlignments(void) {
+ unsigned MaxAlign = BIGGEST_ALIGNMENT;
+#ifdef BIGGEST_FIELD_ALIGNMENT
+ MaxAlign = MIN(MaxAlign, BIGGEST_FIELD_ALIGNMENT);
+#endif
- /* Some targets do funny things with structs. Form a struct that has a
- * character member as the first element, then Type as the second element.
- * If that alignment is less than BasicAlignment, use it.
- */
- tree recordtype = (*lang_hooks.types.make_type) (RECORD_TYPE);
- tree field, fields;
- /* First character field. */
- fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intQI_type_node);
-
- /* A field of type Type. */
- field = build_decl (FIELD_DECL, NULL_TREE, Type);
- TREE_CHAIN (field) = fields;
- finish_builtin_struct(recordtype, "", field, NULL_TREE);
-
- llvm_type_dump(llvm_type_get_from_tree(recordtype));
+#ifdef LLVM_TARGET_MAX_ALIGN_IS_POINTER_SIZE
+ /* Targets like PowerPC where the longs and doubles are 4-byte aligned. */
+ MaxAlign = MIN(MaxAlign, POINTER_SIZE/BITS_PER_UNIT);
+#endif
- TestAlignment = TYPE_ALIGN(recordtype);
- BasicAlignment = MIN(BasicAlignment, TestAlignment);
- return BasicAlignment/8;
-}
-
-static void InitializeAlignments(void) {
/* Figure out the alignments of the primitive types. */
PrimitiveAlignments[BoolTyID] = 1;
PrimitiveAlignments[SByteTyID] = 1;
PrimitiveAlignments[UByteTyID] = 1;
- PrimitiveAlignments[ShortTyID] = getMinTargetAlignment(intHI_type_node);
- PrimitiveAlignments[UShortTyID] =
- getMinTargetAlignment(unsigned_intHI_type_node);
- PrimitiveAlignments[IntTyID] = getMinTargetAlignment(intSI_type_node);
- PrimitiveAlignments[UIntTyID] =
- getMinTargetAlignment(unsigned_intSI_type_node);
- PrimitiveAlignments[LongTyID] = getMinTargetAlignment(intDI_type_node);
- PrimitiveAlignments[ULongTyID] =
- getMinTargetAlignment(unsigned_intDI_type_node);
- PrimitiveAlignments[FloatTyID] = getMinTargetAlignment(float_type_node);
- PrimitiveAlignments[DoubleTyID] = getMinTargetAlignment(double_type_node);
- PrimitiveAlignments[PointerTyID] = getMinTargetAlignment(ptr_type_node);
+ PrimitiveAlignments[ShortTyID] = PrimitiveAlignments[UShortTyID]
+ = MIN(2, MaxAlign);
+ PrimitiveAlignments[IntTyID] = PrimitiveAlignments[UIntTyID]
+ = MIN(4, MaxAlign);
+ PrimitiveAlignments[ULongTyID] = PrimitiveAlignments[LongTyID]
+ = MIN(8, MaxAlign);
+ PrimitiveAlignments[FloatTyID] = MIN(4, MaxAlign);
+ PrimitiveAlignments[DoubleTyID] = MIN(8, MaxAlign);
+ PrimitiveAlignments[PointerTyID] = MIN(POINTER_SIZE/BITS_PER_UNIT, MaxAlign);
}
unsigned llvm_type_get_alignment(llvm_type *Ty) {
@@ -739,7 +721,7 @@
llvm_type_print(FieldTy, stderr);
fprintf(stderr, " name='%s' talign=%d dalign=%d\n", DECL_NAME(field) ?
IDENTIFIER_POINTER(DECL_NAME(field)) : "<empty>",
- GetFieldAlignmentInBits(field), TYPE_ALIGN(TREE_TYPE(field))/8);
+ GetFieldAlignmentInBytes(field), TYPE_ALIGN(TREE_TYPE(field))/8);
}
#endif
@@ -787,32 +769,33 @@
llvm_type *Ty = llvm_type_get_from_tree(TREE_TYPE(field));
/* Get the starting offset in the record... */
unsigned StartOffset = GetFieldOffset(field); /* In bits */
- unsigned BitAlignment = GetFieldAlignmentInBits(field); /* In bits */
- unsigned ByteAlignment = (BitAlignment+7)/8;
+ unsigned ByteAlignment = llvm_type_get_alignment(Ty);
if (!TypeIsRecursivelyIntegral(Ty)) { /* Not an integral field? */
+ unsigned OrigSize = *Size;
/* If this field is not an integral type, just include it directly. */
assert((StartOffset & 7) == 0 && "Member not byte aligned??");
/* Round *Size up to take into consideration alignment of this field */
*Size = (*Size + ByteAlignment - 1) & ~(ByteAlignment-1);
- /* Check to see if there is "magic padding" that got inserted into the
- * structure. This can happen, for example, when the C++ ABI declares that
- * two types to not exist at the same offset. For this reason, a byte of
- * padding is inserted, and then the layout of the next element occurs at
- * whatever alignment is reasonable for it.
+ /* Check to see if the next element starts further from the previous element
+ * than the LLVM alignment would put it. If so, insert some dummy padding
+ * to ensure that the LLVM conception of where this element lands is the
+ * same as what GCC thinks.
*/
- if (*Size < StartOffset/8)
- /* Only fix things if it is because of this "magic padding" */
- if (*Size + ByteAlignment == StartOffset/8) {
- ElementTys[*Idx] = UByteTy; /* Random pad element */
- ElementOffsets[*Idx] = *Size;
- ElementAlignments[*Idx] = 1;
- ++*Idx;
- *Size = StartOffset/8;
- }
-
+ if (*Size < StartOffset/8) {
+ unsigned PadBytes = StartOffset/8 - OrigSize;
+ if (PadBytes == 1)
+ ElementTys[*Idx] = UByteTy;
+ else
+ ElementTys[*Idx] = llvm_type_get_array(UByteTy, PadBytes);
+ ElementOffsets[*Idx] = OrigSize;
+ ElementAlignments[*Idx] = 1;
+ ++*Idx;
+ *Size = OrigSize + PadBytes;
+ }
+
#if 0 /* FIXME: This assertion should be kept!!! */
assert(*Size == StartOffset/8 &&
"Member does not start where we think it does?");
@@ -826,14 +809,17 @@
DECL_BIT_FIELD(field)) {
unsigned NumPads;
unsigned DeclSize = GetDeclSize(field);
+ unsigned FieldCBitAlignment = GetFieldAlignmentInBits(field);
+ unsigned FieldCByteAlignment = (FieldCBitAlignment+7)/8;
/* Is it attempting to align the current offset to some value? */
if (DeclSize == 0) {
- NumPads = ByteAlignment - (*Size % ByteAlignment);
- if (NumPads == ByteAlignment) NumPads = 0;
- assert((*Size+NumPads) % ByteAlignment == 0 &&"Incorrect padding calc?");
+ NumPads = FieldCByteAlignment - (*Size % FieldCByteAlignment);
+ if (NumPads == FieldCByteAlignment) NumPads = 0;
+ assert((*Size+NumPads) % FieldCByteAlignment == 0 &&
+ "Incorrect padding calc?");
#if DEBUG_STRUCT_LAYOUT
fprintf(stderr, "Anon field: align=%db pads = %d ",
- BitAlignment, NumPads);
+ FieldCByteAlignment, NumPads);
PrintFieldInfo(field);
#endif
} else {
@@ -864,15 +850,18 @@
* if the alignment allows for it. Thus, we start out with the element
* size, and round up to the alignment as necessary.
*/
- unsigned ElSize = GetDeclSize(field); /* In bits */
+ unsigned ElSizeInBits = GetDeclSize(field); /* In bits */
+ unsigned FieldCBitAlignment = GetFieldAlignmentInBits(field);
+ unsigned FieldCByteAlignment = (FieldCBitAlignment+7)/8;
+
int HasSignedField;
unsigned StartByte;
- if (ElSize && BitAlignment > ElSize) ElSize = BitAlignment;
+ if (ElSizeInBits) ElSizeInBits = MAX(ElSizeInBits, FieldCBitAlignment);
HasSignedField = !TREE_UNSIGNED(TREE_TYPE(field));
/* Calculate the first byte occupied by this field */
- StartByte = StartOffset/8 - (StartOffset/8) % ByteAlignment;
+ StartByte = StartOffset/8 - (StartOffset/8) % FieldCByteAlignment;
/* Check to see if we have emitted any structure elements that overlap with
* the current bitfield.
@@ -882,9 +871,9 @@
* encompasses this type. If so, we just have to update the signedness if
* the field is not yet signed.
*/
- if (StartByte*8+ElSize <= *Size * 8) {
+ if (StartByte*8+ElSizeInBits <= *Size * 8) {
assert(ElementOffsets[*Idx-1] <= StartByte &&
- ElementAlignments[*Idx-1] >= ByteAlignment &&
+ ElementAlignments[*Idx-1] >= FieldCByteAlignment &&
"Less aligned field overlaps with later, more aligned, field?");
/* If the last field is a bool, expand it to be a uchar */
if (ElementTys[*Idx-1] == BoolTy)
@@ -910,8 +899,8 @@
} while (*Idx && *Size > StartByte);
/* Output this as a series of integer fields. */
- while (ElSize > 64) {
- unsigned UnitSize = ElSize & 63;
+ while (ElSizeInBits > 64) {
+ unsigned UnitSize = ElSizeInBits & 63;
/* Eliminate all but one bit from the size */
if ((UnitSize & (UnitSize-1)) != 0)
UnitSize = UnitSize ^ (UnitSize & (UnitSize-1));
@@ -923,10 +912,27 @@
ElementAlignments[*Idx] = 1;
++*Idx;
StartByte += UnitSize/8;
- ElSize -= UnitSize;
+ ElSizeInBits -= UnitSize;
}
- Ty = llvm_type_get_integer(ElSize, !HasSignedField);
+ Ty = llvm_type_get_integer(ElSizeInBits, !HasSignedField);
+ }
+
+ /* Check to see if the next element starts further from the previous element
+ * than the LLVM alignment would put it. If so, insert some dummy padding
+ * to ensure that the LLVM conception of where this element lands is the
+ * same as what GCC thinks.
+ */
+ if (((*Size + ByteAlignment - 1) & ~(ByteAlignment-1)) < StartOffset/8) {
+ unsigned PadBytes = StartOffset/8 - *Size;
+ if (PadBytes == 1)
+ ElementTys[*Idx] = UByteTy;
+ else
+ ElementTys[*Idx] = llvm_type_get_array(UByteTy, PadBytes);
+ ElementOffsets[*Idx] = *Size;
+ ElementAlignments[*Idx] = 1;
+ ++*Idx;
+ *Size = *Size + PadBytes;
}
/* Check to see if there is "magic padding" that got inserted into the
@@ -939,7 +945,7 @@
/* Only fix things if it is because of this "magic padding" */
if (*Size + ByteAlignment == StartByte) {
/* Random pad element */
- ElementTys[*Idx] = llvm_type_get_integer(BitAlignment, 1);
+ ElementTys[*Idx] = llvm_type_get_integer(ByteAlignment*8, 1);
ElementOffsets[*Idx] = *Size;
ElementAlignments[*Idx] = ByteAlignment;
++*Idx;
@@ -1443,13 +1449,46 @@
#endif
}
- /* Empty C++ structures == { ubyte } in LLVM so that sizes are correct. */
- if (Idx == 0 && (int)TREE_INT_CST_LOW(TYPE_SIZE(type)) == 8) {
- StructElements[0] = UByteTy;
- ElementOffsets[0] = 0;
- ++Idx;
- }
+ /* If we are missing elements from the end of the structure (which
+ * contribute to its size but are not accessed by the program), add dummy
+ * elements so that the LLVM code will have the right size for the
+ * structure.
+ */
+ {
+ unsigned GCCTypeSize = ((unsigned)TREE_INT_CST_LOW(TYPE_SIZE(type))+7)/8;
+ unsigned LLVMTypeSize, LLVMStructAlign = 1, i;
+
+ /* To determine what LLVM will think the size of this struct is, compute
+ * the LLVM alignment the struct will have.
+ */
+ for (i = 0; i != Idx; ++i) {
+ unsigned EltAlign = llvm_type_get_alignment(StructElements[i]);
+ LLVMStructAlign = MAX(LLVMStructAlign, EltAlign);
+ }
+
+ /* The LLVM size of the struct will be the current size, rounded up to the
+ * next multiple of StructAlign.
+ */
+ assert((LLVMStructAlign & (LLVMStructAlign-1)) == 0 &&
+ "Alignment not a power of 2!");
+ LLVMTypeSize = (Size+LLVMStructAlign-1) & ~(LLVMStructAlign-1);
+ /* If the LLVM type will end up being too small, add elements to the end
+ * of the struct to pad it out.
+ */
+ if (LLVMTypeSize < GCCTypeSize) {
+ unsigned PadBytes = GCCTypeSize - Size;
+ if (PadBytes == 1)
+ StructElements[Idx] = UByteTy;
+ else
+ StructElements[Idx] = llvm_type_get_array(UByteTy, PadBytes);
+ ElementOffsets[Idx] = Size;
+ ElementAlignments[Idx] = 1;
+ ++Idx;
+ Size += PadBytes;
+ }
+ }
+
/* End of the hack, set the real number of elements. */
Result->NumElements = Idx;
More information about the llvm-commits
mailing list