[llvm-commits] [125160] Better support for variable size struct fields.
dpatel at apple.com
dpatel at apple.com
Mon Mar 19 13:55:02 PDT 2007
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));
More information about the llvm-commits
mailing list