[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