[llvm-branch-commits] [llvm-gcc-branch] r82631 - in /llvm-gcc-4.2/branches/Apple/Leela/gcc: llvm-convert.cpp llvm-internal.h llvm-types.cpp
Bob Wilson
bob.wilson at apple.com
Wed Sep 23 09:48:20 PDT 2009
Author: bwilson
Date: Wed Sep 23 11:48:20 2009
New Revision: 82631
URL: http://llvm.org/viewvc/llvm-project?rev=82631&view=rev
Log:
$ svn merge -c 82486 https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk
--- Merging r82486 into '.':
U gcc/llvm-types.cpp
$ svn merge -c 82487 https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk
--- Merging r82487 into '.':
G gcc/llvm-types.cpp
$ svn merge -c 82494 https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk
--- Merging r82494 into '.':
G gcc/llvm-types.cpp
$ svn merge -c 82630 https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk
--- Merging r82630 into '.':
U gcc/llvm-convert.cpp
U gcc/llvm-internal.h
G gcc/llvm-types.cpp
Modified:
llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-convert.cpp
llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-internal.h
llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-types.cpp
Modified: llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-convert.cpp?rev=82631&r1=82630&r2=82631&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-convert.cpp Wed Sep 23 11:48:20 2009
@@ -7828,28 +7828,51 @@
assert(VEC_length(constructor_elt, elt) == 1
&& "Union CONSTRUCTOR with multiple elements?");
- std::vector<Constant*> Elts;
+ ConstantLayoutInfo LayoutInfo(getTargetData());
+
// Convert the constant itself.
- Elts.push_back(Convert(VEC_index(constructor_elt, elt, 0)->value));
+ Constant *Val = Convert(VEC_index(constructor_elt, elt, 0)->value);
+
+ // Unions are initialized using the first member field. Find it.
+ tree Field = TYPE_FIELDS(TREE_TYPE(exp));
+ assert(Field && "cannot initialize union with no fields");
+ while (TREE_CODE(Field) != FIELD_DECL) {
+ Field = TREE_CHAIN(Field);
+ assert(Field && "cannot initialize union with no fields");
+ }
+
+ // If this is a non-bitfield value, just slap it onto the end of the struct
+ // with the appropriate padding etc. If it is a bitfield, we have more
+ // processing to do.
+ if (!isBitfield(Field))
+ LayoutInfo.AddFieldToRecordConstant(Val, 0);
+ else {
+ // Bitfields can only be initialized with constants (integer constant
+ // expressions).
+ ConstantInt *ValC = cast<ConstantInt>(Val);
+ uint64_t FieldSizeInBits = getInt64(DECL_SIZE(Field), true);
+ uint64_t ValueSizeInBits = Val->getType()->getPrimitiveSizeInBits();
+
+ assert(ValueSizeInBits >= FieldSizeInBits &&
+ "disagreement between LLVM and GCC on bitfield size");
+ if (ValueSizeInBits != FieldSizeInBits) {
+ // Fields are allowed to be smaller than their type. Simply discard
+ // the unwanted upper bits in the field value.
+ APInt ValAsInt = ValC->getValue();
+ ValC = ConstantInt::get(Context, ValAsInt.trunc(FieldSizeInBits));
+ }
+ LayoutInfo.AddBitFieldToRecordConstant(ValC, 0);
+ }
// If the union has a fixed size, and if the value we converted isn't large
// enough to fill all the bits, add a zero initialized array at the end to pad
// it out.
- tree UnionType = TREE_TYPE(exp);
- if (TYPE_SIZE(UnionType) && TREE_CODE(TYPE_SIZE(UnionType)) == INTEGER_CST) {
- uint64_t UnionSize = ((uint64_t)TREE_INT_CST_LOW(TYPE_SIZE(UnionType))+7)/8;
- uint64_t InitSize = getTargetData().getTypeAllocSize(Elts[0]->getType());
- if (UnionSize != InitSize) {
- const Type *FillTy;
- assert(UnionSize > InitSize && "Init shouldn't be larger than union!");
- if (UnionSize - InitSize == 1)
- FillTy = Type::getInt8Ty(Context);
- else
- FillTy = ArrayType::get(Type::getInt8Ty(Context), UnionSize - InitSize);
- Elts.push_back(Constant::getNullValue(FillTy));
- }
- }
- return ConstantStruct::get(Context, Elts, false);
+ tree UnionTypeSizeTree = TYPE_SIZE(TREE_TYPE(exp));
+ if (UnionTypeSizeTree && TREE_CODE(UnionTypeSizeTree) == INTEGER_CST)
+ LayoutInfo.HandleTailPadding(getInt64(UnionTypeSizeTree, true));
+
+ return ConstantStruct::get(Context, LayoutInfo.ResultElts,
+ LayoutInfo.StructIsPacked);
}
//===----------------------------------------------------------------------===//
Modified: llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-internal.h?rev=82631&r1=82630&r2=82631&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-internal.h Wed Sep 23 11:48:20 2009
@@ -168,6 +168,7 @@
void SetFieldIndex(tree_node *field_decl, unsigned int Index);
bool DecodeStructFields(tree_node *Field, StructTypeConversionInfo &Info);
void DecodeStructBitField(tree_node *Field, StructTypeConversionInfo &Info);
+ void SelectUnionMember(tree_node *type, StructTypeConversionInfo &Info);
};
extern TypeConverter *TheTypeConverter;
Modified: llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-types.cpp?rev=82631&r1=82630&r2=82631&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Leela/gcc/llvm-types.cpp Wed Sep 23 11:48:20 2009
@@ -703,9 +703,9 @@
debug_tree(type);
abort();
case VOID_TYPE: return SET_TYPE_LLVM(type, Type::getVoidTy(Context));
- case RECORD_TYPE: return ConvertRECORD(type, orig_type);
+ case RECORD_TYPE:
case QUAL_UNION_TYPE:
- case UNION_TYPE: return ConvertUNION(type, orig_type);
+ case UNION_TYPE: return ConvertRECORD(type, orig_type);
case BOOLEAN_TYPE: {
if (const Type *Ty = GET_TYPE_LLVM(type))
return Ty;
@@ -1597,7 +1597,7 @@
void dump() const;
};
-// Add new element which is a bit field. Size is not the size of bit filed,
+// Add new element which is a bit field. Size is not the size of bit field,
// but size of bits required to determine type of new Field which will be
// used to access this bit field.
void StructTypeConversionInfo::addNewBitField(uint64_t Size,
@@ -1849,7 +1849,7 @@
/// DecodeStructFields - This method decodes the specified field, if it is a
/// FIELD_DECL, adding or updating the specified StructTypeConversionInfo to
-/// reflect it. Return tree if field is decoded correctly. Otherwise return
+/// reflect it. Return true if field is decoded correctly. Otherwise return
/// false.
bool TypeConverter::DecodeStructFields(tree Field,
StructTypeConversionInfo &Info) {
@@ -2033,10 +2033,86 @@
Info.addNewBitField(FieldSizeInBits, FirstUnallocatedByte);
}
+/// UnionHasOnlyZeroOffsets - Check if a union type has only members with
+/// offsets that are zero, e.g., no Fortran equivalences.
+static bool UnionHasOnlyZeroOffsets(tree type) {
+ for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
+ if (TREE_CODE(Field) != FIELD_DECL) continue;
+ if (getFieldOffsetInBits(Field) != 0)
+ return false;
+ }
+ return true;
+}
-/// ConvertRECORD - We know that 'type' is a RECORD_TYPE: convert it to an LLVM
-/// type.
-// A note on C++ virtual base class layout. Consider the following example:
+/// SelectUnionMember - Find the union member with the largest aligment. If
+/// there are multiple types with the same alignment, select the one with
+/// the largest size. If the type with max. align is smaller than other types,
+/// then we will add padding later on anyway to match union size.
+void TypeConverter::SelectUnionMember(tree type,
+ StructTypeConversionInfo &Info) {
+ const Type *UnionTy = 0;
+ tree GccUnionTy = 0;
+ tree UnionField = 0;
+ unsigned MaxAlignSize = 0, MaxAlign = 0;
+ for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
+ if (TREE_CODE(Field) != FIELD_DECL) continue;
+ assert(getFieldOffsetInBits(Field) == 0 && "Union with non-zero offset?");
+
+ // Skip fields that are known not to be present.
+ if (TREE_CODE(type) == QUAL_UNION_TYPE &&
+ integer_zerop(DECL_QUALIFIER(Field)))
+ continue;
+
+ tree TheGccTy = TREE_TYPE(Field);
+
+ // Skip zero-length fields; ConvertType refuses to construct a type
+ // of size 0.
+ if (DECL_SIZE(Field) &&
+ TREE_CODE(DECL_SIZE(Field)) == INTEGER_CST &&
+ TREE_INT_CST_LOW(DECL_SIZE(Field)) == 0)
+ continue;
+
+ const Type *TheTy = ConvertType(TheGccTy);
+ unsigned Size = Info.getTypeSize(TheTy);
+ unsigned Align = Info.getTypeAlignment(TheTy);
+
+ adjustPaddingElement(GccUnionTy, TheGccTy);
+
+ // Select TheTy as union type if it is more aligned than any other. If
+ // more than one field achieves the maximum alignment then choose the
+ // biggest.
+ if (UnionTy == 0 || Align > MaxAlign ||
+ (Align == MaxAlign && Size > MaxAlignSize)) {
+ UnionTy = TheTy;
+ UnionField = Field;
+ GccUnionTy = TheGccTy;
+ MaxAlignSize = Size;
+ MaxAlign = Align;
+ }
+
+ // Skip remaining fields if this one is known to be present.
+ if (TREE_CODE(type) == QUAL_UNION_TYPE &&
+ integer_onep(DECL_QUALIFIER(Field)))
+ break;
+ }
+
+ if (UnionTy) { // Not an empty union.
+ if (8 * Info.getTypeAlignment(UnionTy) > TYPE_ALIGN(type))
+ Info.markAsPacked();
+
+ if (isBitfield(UnionField)) {
+ unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(UnionField));
+ Info.addNewBitField(FieldSizeInBits, 0);
+ } else {
+ Info.allFieldsAreNotBitFields();
+ Info.addElement(UnionTy, 0, Info.getTypeSize(UnionTy));
+ }
+ }
+}
+
+/// ConvertRECORD - Convert a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE to
+/// an LLVM type.
+// A note on C++ virtual base class layout. Consider the following example:
// class A { public: int i0; };
// class B : public virtual A { public: int i1; };
// class C : public virtual A { public: int i2; };
@@ -2069,9 +2145,11 @@
return Ty;
}
+ bool IsStruct = (TREE_CODE(type) == RECORD_TYPE);
if (TYPE_SIZE(type) == 0) { // Forward declaration?
const Type *Ty = OpaqueType::get(Context);
- TheModule->addTypeName(GetTypeName("struct.", orig_type), Ty);
+ TheModule->addTypeName(GetTypeName(IsStruct ? "struct." : "union.",
+ orig_type), Ty);
return TypeDB.setType(type, Ty);
}
@@ -2087,29 +2165,40 @@
// of fields bear some resemblance to reality. Also alter any fields that
// are less aligned than their type, as the type may not get tail padding
// in this case.
- FixUpFields(type);
-
- // Convert over all of the elements of the struct.
- bool retryAsPackedStruct = false;
- for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
- if (DecodeStructFields(Field, *Info) == false) {
- retryAsPackedStruct = true;
- break;
- }
- }
+ if (IsStruct)
+ FixUpFields(type);
- if (retryAsPackedStruct) {
- delete Info;
- Info = new StructTypeConversionInfo(*TheTarget, TYPE_ALIGN(type) / 8, true);
+ // Workaround to get Fortran EQUIVALENCE working.
+ // TODO: Unify record and union logic and handle this optimally.
+ bool HasOnlyZeroOffsets = (!IsStruct && UnionHasOnlyZeroOffsets(type));
+ if (HasOnlyZeroOffsets) {
+ SelectUnionMember(type, *Info);
+ } else {
+ // Convert over all of the elements of the struct.
+ bool retryAsPackedStruct = false;
for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
if (DecodeStructFields(Field, *Info) == false) {
- assert(0 && "Unable to decode struct fields.");
+ retryAsPackedStruct = true;
+ break;
+ }
+ }
+
+ if (retryAsPackedStruct) {
+ delete Info;
+ Info = new StructTypeConversionInfo(*TheTarget, TYPE_ALIGN(type) / 8,
+ true);
+ for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
+ if (DecodeStructFields(Field, *Info) == false) {
+ assert(0 && "Unable to decode struct fields.");
+ }
}
}
}
- // If the LLVM struct requires explicit tail padding to be the same size as
- // the GCC struct, insert tail padding now. This handles, e.g., "{}" in C++.
+ // Insert tail padding if the LLVM struct requires explicit tail padding to
+ // be the same size as the GCC struct or union. This handles, e.g., "{}" in
+ // C++, and cases where a union has larger alignment than the largest member
+ // does.
if (TYPE_SIZE(type) && TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST) {
uint64_t GCCTypeSize = getInt64(TYPE_SIZE_UNIT(type), true);
uint64_t LLVMStructSize = Info->getSizeAsLLVMStruct();
@@ -2131,26 +2220,24 @@
if (((GCCTypeSize-LLVMStructSize) % 4) == 0 &&
(Info->getAlignmentAsLLVMStruct() %
Info->getTypeAlignment(Type::getInt32Ty(Context))) == 0) {
- // insert array of i32
- unsigned Int32ArraySize = (GCCTypeSize-LLVMStructSize)/4;
+ // Insert array of i32.
+ unsigned Int32ArraySize = (GCCTypeSize-LLVMStructSize) / 4;
const Type *PadTy =
ArrayType::get(Type::getInt32Ty(Context), Int32ArraySize);
Info->addElement(PadTy, GCCTypeSize - LLVMLastElementEnd,
Int32ArraySize, true /* Padding Element */);
} else {
- const Type *PadTy =
- ArrayType::get(Type::getInt8Ty(Context), GCCTypeSize-LLVMStructSize);
+ const Type *PadTy = ArrayType::get(Type::getInt8Ty(Context),
+ GCCTypeSize-LLVMStructSize);
Info->addElement(PadTy, GCCTypeSize - LLVMLastElementEnd,
GCCTypeSize - LLVMLastElementEnd,
true /* Padding Element */);
-
}
}
}
} else
Info->RemoveExtraBytes();
-
// Now that the LLVM struct is finalized, figure out a safe place to index to
// and set index values for each FieldDecl that doesn't start at a variable
// offset.
@@ -2158,45 +2245,52 @@
for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
if (TREE_CODE(Field) == FIELD_DECL &&
TREE_CODE(DECL_FIELD_OFFSET(Field)) == INTEGER_CST) {
- uint64_t FieldOffsetInBits = getFieldOffsetInBits(Field);
- tree FieldType = getDeclaredType(Field);
- const Type *FieldTy = ConvertType(FieldType);
-
- // 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 (isBitfield(Field)) {
- // If this is a bitfield, the declared type must be an integral type.
- 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;
-
- // Skip 'int:0', which just affects layout.
- if (integer_zerop(DECL_SIZE(Field)))
- continue;
- }
+ if (HasOnlyZeroOffsets) {
+ // Set the field idx to zero for all members of a union.
+ SetFieldIndex(Field, 0);
+ } else {
+ uint64_t FieldOffsetInBits = getFieldOffsetInBits(Field);
+ tree FieldType = getDeclaredType(Field);
+ const Type *FieldTy = ConvertType(FieldType);
+
+ // 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 (isBitfield(Field)) {
+ // If this is a bitfield, the declared type must be an integral type.
+ 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;
+
+ // Skip 'int:0', which just affects layout.
+ if (integer_zerop(DECL_SIZE(Field)))
+ continue;
+ }
- // Figure out if this field is zero bits wide, e.g. {} or [0 x int].
- bool isZeroSizeField = FieldTy->isSized() &&
- getTargetData().getTypeSizeInBits(FieldTy) == 0;
-
- unsigned FieldNo =
- Info->getLLVMFieldFor(FieldOffsetInBits, CurFieldNo, isZeroSizeField);
- SetFieldIndex(Field, FieldNo);
-
- assert((isBitfield(Field) || FieldNo == ~0U ||
- FieldOffsetInBits == 8*Info->ElementOffsetInBytes[FieldNo]) &&
- "Wrong LLVM field offset!");
+ // Figure out if this field is zero bits wide, e.g. {} or [0 x int].
+ bool isZeroSizeField = FieldTy->isSized() &&
+ getTargetData().getTypeSizeInBits(FieldTy) == 0;
+
+ unsigned FieldNo =
+ Info->getLLVMFieldFor(FieldOffsetInBits, CurFieldNo, isZeroSizeField);
+ SetFieldIndex(Field, FieldNo);
+
+ assert((isBitfield(Field) || FieldNo == ~0U ||
+ FieldOffsetInBits == 8*Info->ElementOffsetInBytes[FieldNo]) &&
+ "Wrong LLVM field offset!");
+ }
}
// Put the original gcc struct back the way it was; necessary to prevent the
// binfo-walking code in cp/class from getting confused.
- RestoreOriginalFields(type);
+ if (IsStruct)
+ RestoreOriginalFields(type);
const Type *ResultTy = Info->getLLVMType();
StructTypeInfoMap[type] = Info;
@@ -2210,11 +2304,11 @@
const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
// Finally, set the name for the type.
- TheModule->addTypeName(GetTypeName("struct.", orig_type),
- GET_TYPE_LLVM(type));
+ TheModule->addTypeName(GetTypeName(IsStruct ? "struct." : "union.",
+ orig_type), GET_TYPE_LLVM(type));
// We have finished converting this struct. See if the is the outer-most
- // struct being converted by ConvertType.
+ // struct or union being converted by ConvertType.
ConvertingStruct = OldConvertingStruct;
if (!ConvertingStruct) {
@@ -2236,185 +2330,4 @@
return GET_TYPE_LLVM(type);
}
-
-/// ConvertUNION - We know that 'type' is a UNION_TYPE or a QUAL_UNION_TYPE:
-/// convert it to an LLVM type.
-const Type *TypeConverter::ConvertUNION(tree type, tree orig_type) {
- if (const Type *Ty = GET_TYPE_LLVM(type)) {
- // If we already compiled this type, and if it was not a forward
- // definition that is now defined, use the old type.
- if (!isa<OpaqueType>(Ty) || TYPE_SIZE(type) == 0)
- return Ty;
- }
-
- if (TYPE_SIZE(type) == 0) { // Forward declaraion?
- const Type *Ty = OpaqueType::get(Context);
- TheModule->addTypeName(GetTypeName("union.", orig_type), Ty);
- return TypeDB.setType(type, Ty);
- }
-
- // Note that we are compiling a struct now.
- bool OldConvertingStruct = ConvertingStruct;
- ConvertingStruct = true;
-
- // Find the type with the largest aligment, and if we have multiple types with
- // the same alignment, select one with largest size. If type with max. align
- // is smaller then other types then we will add padding later on anyway to
- // match union size.
- const TargetData &TD = getTargetData();
- const Type *UnionTy = 0;
- tree GccUnionTy = 0;
- unsigned MaxAlignSize = 0, MaxAlign = 0;
- for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
- if (TREE_CODE(Field) != FIELD_DECL) continue;
-// assert(getFieldOffsetInBits(Field) == 0 && "Union with non-zero offset?");
- // Workaround to get Fortran EQUIVALENCE working.
- // TODO: Unify record and union logic and handle this optimally.
- if (getFieldOffsetInBits(Field) != 0) {
- ConvertingStruct = OldConvertingStruct;
- return ConvertRECORD(type, orig_type);
- }
-
- // Set the field idx to zero for all fields.
- SetFieldIndex(Field, 0);
-
- // Skip fields that are known not to be present.
- if (TREE_CODE(type) == QUAL_UNION_TYPE &&
- integer_zerop(DECL_QUALIFIER(Field)))
- continue;
-
- tree TheGccTy = TREE_TYPE(Field);
-
- // Skip zero-length fields; ConvertType refuses to construct a type
- // of size 0.
- if (DECL_SIZE(Field) &&
- TREE_CODE(DECL_SIZE(Field))==INTEGER_CST &&
- TREE_INT_CST_LOW(DECL_SIZE(Field))==0)
- continue;
-#ifdef TARGET_POWERPC
- // Normally gcc reduces the size of bitfields to the size necessary
- // to hold the bits, e.g. a 1-bit field becomes QI. It does not do
- // this for bool, which is no problem on most targets because
- // sizeof(bool)==1. On darwin ppc32, however, sizeof(bool)==4, so
- // we can have field types bigger than the union type here. Evade
- // this by creating an appropriate int type here.
- //
- // It's possible this issue is not specific to ppc, but I doubt it.
-
- if (TREE_CODE(TheGccTy) == BOOLEAN_TYPE &&
- TYPE_SIZE_UNIT(TheGccTy) &&
- DECL_SIZE_UNIT(Field) &&
- TREE_CODE(DECL_SIZE_UNIT(Field)) == INTEGER_CST &&
- TREE_CODE(TYPE_SIZE_UNIT(TheGccTy)) == INTEGER_CST &&
- TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TheGccTy)) >
- TREE_INT_CST_LOW(DECL_SIZE_UNIT(Field))) {
- bool sign = DECL_UNSIGNED(Field);
- switch(TREE_INT_CST_LOW(DECL_SIZE_UNIT(Field))) {
- case 1: TheGccTy = sign ? intQI_type_node : unsigned_intQI_type_node;
- break;
- case 2: TheGccTy = sign ? intHI_type_node : unsigned_intHI_type_node;
- break;
- case 4: TheGccTy = sign ? intSI_type_node : unsigned_intSI_type_node;
- break;
- case 8: TheGccTy = sign ? intDI_type_node : unsigned_intDI_type_node;
- break;
- default: assert(0 && "Unexpected field size"); break;
- }
- }
-#endif
- const Type *TheTy = ConvertType(TheGccTy);
- unsigned Size = TD.getTypeAllocSize(TheTy);
- unsigned Align = TD.getABITypeAlignment(TheTy);
-
- adjustPaddingElement(GccUnionTy, TheGccTy);
-
- // Select TheTy as union type if it is more aligned than any other. If more
- // than one field achieves the maximum alignment then choose the biggest.
- bool useTheTy;
- if (UnionTy == 0)
- useTheTy = true;
- else if (Align < MaxAlign)
- useTheTy = false;
- else if (Align > MaxAlign)
- useTheTy = true;
- else if (Size > MaxAlignSize)
- useTheTy = true;
- else
- useTheTy = false;
-
- if (useTheTy) {
- UnionTy = TheTy;
- GccUnionTy = TheGccTy;
- MaxAlignSize = Size;
- MaxAlign = Align;
- }
-
- // Skip remaining fields if this one is known to be present.
- if (TREE_CODE(type) == QUAL_UNION_TYPE &&
- integer_onep(DECL_QUALIFIER(Field)))
- break;
- }
-
- std::vector<const Type*> UnionElts;
- unsigned EltAlign = 0;
- unsigned EltSize = 0;
- if (UnionTy) { // Not an empty union.
- EltAlign = TD.getABITypeAlignment(UnionTy);
- EltSize = TD.getTypeAllocSize(UnionTy);
- UnionElts.push_back(UnionTy);
- }
-
- // If the LLVM struct requires explicit tail padding to be the same size as
- // the GCC union, insert tail padding now. This handles cases where the union
- // has larger alignment than the largest member does, thus requires tail
- // padding.
- if (TYPE_SIZE(type) && TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST) {
- uint64_t GCCTypeSize = getInt64(TYPE_SIZE_UNIT(type), true);
-
- if (EltSize != GCCTypeSize) {
- assert(EltSize < GCCTypeSize &&
- "LLVM type size doesn't match GCC type size!");
- const Type *PadTy = Type::getInt8Ty(Context);
- if (GCCTypeSize-EltSize != 1)
- PadTy = ArrayType::get(PadTy, GCCTypeSize-EltSize);
- UnionElts.push_back(PadTy);
- }
- }
-
- bool isPacked = 8 * EltAlign > TYPE_ALIGN(type);
- const Type *ResultTy = StructType::get(Context, UnionElts, isPacked);
- const OpaqueType *OldTy = cast_or_null<OpaqueType>(GET_TYPE_LLVM(type));
- TypeDB.setType(type, ResultTy);
-
- // If there was a forward declaration for this type that is now resolved,
- // refine anything that used it to the new type.
- if (OldTy)
- const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
-
- // Finally, set the name for the type.
- TheModule->addTypeName(GetTypeName("struct.", orig_type),
- GET_TYPE_LLVM(type));
-
- // We have finished converting this union. See if the is the outer-most
- // union being converted by ConvertType.
- ConvertingStruct = OldConvertingStruct;
- if (!ConvertingStruct) {
- // If this is the outer-most level of structness, resolve any pointers
- // that were deferred.
- while (!PointersToReresolve.empty()) {
- if (tree PtrTy = PointersToReresolve.back()) {
- ConvertType(PtrTy); // Reresolve this pointer type.
- assert((PointersToReresolve.empty() ||
- PointersToReresolve.back() != PtrTy) &&
- "Something went wrong with pointer resolution!");
- } else {
- // Null marker element.
- PointersToReresolve.pop_back();
- }
- }
- }
-
- return GET_TYPE_LLVM(type);
-}
-
/* LLVM LOCAL end (ENTIRE FILE!) */
More information about the llvm-branch-commits
mailing list