[llvm-commits] CVS: llvm-gcc/gcc/llvm-expand.c
Chris Lattner
lattner at cs.uiuc.edu
Sat Nov 27 16:41:10 PST 2004
Changes in directory llvm-gcc/gcc:
llvm-expand.c updated: 1.67 -> 1.68
---
Log message:
Add support for structures with members at non-constant offsets.
This fixes Regression/CFrontend/2004-11-27-VariableSizeInStructure.c and
PR360: http://llvm.cs.uiuc.edu/PR360 .
---
Diffs of the changes: (+30 -7)
Index: llvm-gcc/gcc/llvm-expand.c
diff -u llvm-gcc/gcc/llvm-expand.c:1.67 llvm-gcc/gcc/llvm-expand.c:1.68
--- llvm-gcc/gcc/llvm-expand.c:1.67 Sat Nov 27 18:07:26 2004
+++ llvm-gcc/gcc/llvm-expand.c Sat Nov 27 18:40:58 2004
@@ -3739,13 +3739,21 @@
}
}
-/* GetFieldOffset - Return the offset (in bits) of a FIELD_DECL in a
- * structure.
+/* GetFieldOffset - Return the offset (in bits) of a FIELD_DECL in a structure.
+ * Note that GCC permits structures with variable sized objects embedded IN
+ * them, like { [N x int], int}. In this case, the offset to the second field
+ * will not be a constant. In this case, we expect the caller to be able to
+ * handle this, and we return a zero for the byte offset (there may still be a
+ * bit offset though).
*/
static unsigned GetFieldOffset(tree Field) {
+ unsigned Result;
assert(DECL_FIELD_BIT_OFFSET(Field) != 0 && DECL_FIELD_OFFSET(Field) != 0);
- return TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(Field)) +
- TREE_INT_CST_LOW(DECL_FIELD_OFFSET(Field))*8;
+ Result = TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(Field));
+
+ if (TREE_CODE(DECL_FIELD_OFFSET(Field)) == INTEGER_CST)
+ Result += TREE_INT_CST_LOW(DECL_FIELD_OFFSET(Field))*8;
+ return Result;
}
/* GetDeclSize - Return the size of the declaration, in bits. */
@@ -3808,6 +3816,9 @@
unsigned FieldIndexVal = llvm_constant_get_integer_val(V2C(FieldIndex));
llvm_type *FieldType = GET_STRUCT_TYPE_ELEMENT(Ty, FieldIndexVal);
unsigned FieldOffset = GetFieldOffset(field);
+ assert(TREE_CODE(DECL_FIELD_OFFSET(field)) == INTEGER_CST &&
+ "Can't handle structures with variable sized objects in them");
+
/*
* Attempt to get the size of the field.
@@ -5392,10 +5403,22 @@
} else {
unsigned ActualOffset = GetFieldDeclOffset(FieldDecl)*8;
unsigned ActualSize;
- llvm_value *FieldNo = DECL_LLVM(FieldDecl);
llvm_type *ResultElTy;
- I = create_gep3(Op0, llvm_constant_intptr_0, FieldNo);
- Result = append_inst(Fn, I);
+
+ if (TREE_CODE(DECL_FIELD_OFFSET(FieldDecl)) == INTEGER_CST) {
+ llvm_value *FieldNo = DECL_LLVM(FieldDecl);
+ I = create_gep3(Op0, llvm_constant_intptr_0, FieldNo);
+ Result = append_inst(Fn, I);
+ } else {
+ /* Otherwise, this field has a variable offset to it. Handle it now. */
+ llvm_value *Offset =
+ llvm_expand_expr(Fn, DECL_FIELD_OFFSET(FieldDecl), 0);
+ Result = cast_if_type_not_equal(Fn, Op0, Offset->Ty);
+ I = create_binary_inst("tmp", O_Add, Offset, Result);
+ Result = append_inst(Fn, I);
+ Result = cast_if_type_not_equal(Fn, Result,
+ llvm_type_get_pointer(FieldDeclTy));
+ }
ResultElTy = GET_POINTER_TYPE_ELEMENT(Result->Ty);
ActualSize = llvm_type_get_size(ResultElTy)*8;
More information about the llvm-commits
mailing list