This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

MS-style bit-field placement


Here's a patch that makes GCC capable of placing bit-fields exactly
like Microsoft compilers do.  Or so it seems to me.

I'm a little bit unsure about whether to separate the three key
behaviors into different #defines, or to just have a single macro to
enable them all.  Opinions?  Ok to install?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* tree.h (record_layout_info_s): Added prev_field.
	* stor-layout.c (start_record_layout): Zero out prev_field.
	(place_field): Use it for BITFIELD_SAME_TYPE_SIZE,
	ZERO_SIZED_BITFIELD_AFFECTS_STRUCT_ALIGNMENT and
	ZERO_SIZED_BITFIELD_WORKS_AFTER_NONZERO_BITFIELD.
	* tm.texi: Document the new macros.

Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.h,v
retrieving revision 1.236
diff -u -p -r1.236 tree.h
--- gcc/tree.h 2001/04/13 21:10:15 1.236
+++ gcc/tree.h 2001/04/14 14:51:31
@@ -2113,6 +2113,8 @@ typedef struct record_layout_info_s
   unsigned int record_align;
   /* The alignment of the record so far, not including padding, in bits.  */
   unsigned int unpacked_align;
+  /* The previous field layed out.  */
+  tree prev_field;
   /* The static variables (i.e., class variables, as opposed to
      instance variables) encountered in T.  */
   tree pending_statics;
Index: gcc/tm.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tm.texi,v
retrieving revision 1.178
diff -u -p -r1.178 tm.texi
--- gcc/tm.texi 2001/04/13 01:42:38 1.178
+++ gcc/tm.texi 2001/04/14 14:51:33
@@ -1118,6 +1118,24 @@ get from @code{PCC_BITFIELD_TYPE_MATTERS
 Like PCC_BITFIELD_TYPE_MATTERS except that its effect is limited to
 aligning a bitfield within the structure.
 
+@findex BITFIELD_SAME_TYPE_SIZE
+@item BITFIELD_SAME_TYPE_SIZE
+If defined to non-zero, a bitfield won't share the same storage unit
+with the previous bitfield if their underlying types have different
+sizes.  In this case, the bitfield will be aligned to the highest
+alignment of the underlying types of itself and of the previous
+bitfield.
+
+@findex ZERO_SIZED_BITFIELD_WORKS_AFTER_NONZERO_BITFIELD
+@item ZERO_SIZED_BITFIELDS_WORKS_AFTER_NONZERO_BITFIELD
+If defined to non-zero, a zero-sized bitfield will be disregarded unless
+it follows a non-zero-sized bitfield.
+
+@findex ZERO_SIZED_BITFIELD_AFFECTS_STRUCT_ALIGNMENT
+@item ZERO_SIZED_BITFIELDS_AFFECTS_STRUCT_ALIGNMENT
+If defined to non-zero, a zero-sized bitfield will affect alignment of
+the whole struct, even if it is unnamed.
+
 @findex MEMBER_TYPE_FORCES_BLK
 @item MEMBER_TYPE_FORCES_BLK (@var{field})
 Return 1 if a structure or array containing @var{field} should be accessed using
Index: gcc/stor-layout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stor-layout.c,v
retrieving revision 1.96
diff -u -p -r1.96 stor-layout.c
--- gcc/stor-layout.c 2001/03/23 16:59:56 1.96
+++ gcc/stor-layout.c 2001/04/14 14:51:33
@@ -475,6 +475,7 @@ start_record_layout (t)
 
   rli->offset = size_zero_node;
   rli->bitpos = bitsize_zero_node;
+  rli->prev_field = 0;
   rli->pending_statics = 0;
   rli->packed_maybe_necessary = 0;
 
@@ -702,6 +703,7 @@ place_field (rli, field)
   else if (TREE_CODE (rli->t) != RECORD_TYPE)
     {
       place_union_field (rli, field);
+      rli->prev_field = field;
       return;
     }
 
@@ -747,6 +749,28 @@ place_field (rli, field)
   /* Record must have at least as much alignment as any field.
      Otherwise, the alignment of the field within the record is
      meaningless.  */
+#ifdef ZERO_SIZED_BITFIELD_AFFECTS_STRUCT_ALIGNMENT
+  if (ZERO_SIZED_BITFIELD_AFFECTS_STRUCT_ALIGNMENT
+      && type != error_mark_node
+      && DECL_BIT_FIELD_TYPE (field)
+      && ! integer_zerop (TYPE_SIZE (type))
+      && integer_zerop (DECL_SIZE (field)))
+    {
+#ifdef ZERO_SIZED_BITFIELD_WORKS_AFTER_NONZERO_BITFIELD
+      if (ZERO_SIZED_BITFIELD_WORKS_AFTER_NONZERO_BITFIELD
+	  && ! (rli->prev_field
+		&& DECL_BIT_FIELD_TYPE (rli->prev_field)
+		&& ! integer_zerop (DECL_SIZE (rli->prev_field))))
+	desired_align = 1;
+      else
+#endif
+	{
+	  rli->record_align = MAX (rli->record_align, desired_align);
+	  rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+	}
+    }	
+  else
+#endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
   if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
       && DECL_BIT_FIELD_TYPE (field)
@@ -899,6 +923,41 @@ place_field (rli, field)
     }
 #endif
 
+#ifdef BITFIELD_SAME_TYPE_SIZE
+  if (BITFIELD_SAME_TYPE_SIZE
+      && TREE_CODE (field) == FIELD_DECL
+      && type != error_mark_node
+      && ! DECL_PACKED (field)
+      && rli->prev_field
+      && host_integerp (DECL_SIZE (field), 1)
+      && host_integerp (rli->offset, 1)
+      && host_integerp (TYPE_SIZE (type), 1)
+      && host_integerp (TYPE_SIZE (TREE_TYPE (rli->prev_field)), 1)
+      && ((DECL_BIT_FIELD_TYPE (rli->prev_field)
+	   && ! integer_zerop (DECL_SIZE (rli->prev_field)))
+	  || (DECL_BIT_FIELD_TYPE (field)
+	      && ! integer_zerop (DECL_SIZE (field))))
+      && ! simple_cst_equal (TYPE_SIZE (type),
+			     TYPE_SIZE (TREE_TYPE (rli->prev_field))))
+    {
+      unsigned int type_align = TYPE_ALIGN (type);
+
+      if (rli->prev_field
+	  && DECL_BIT_FIELD_TYPE (rli->prev_field)
+	  /* If the previous bit-field is zero-sized, we've already
+	     accounted for its alignment needs (or ignored it, if
+	     appropriate) while placing it.  */
+	  && ! integer_zerop (DECL_SIZE (rli->prev_field)))
+	type_align = MAX (type_align,
+			  TYPE_ALIGN (TREE_TYPE (rli->prev_field)));
+
+      if (maximum_field_alignment != 0)
+	type_align = MIN (type_align, maximum_field_alignment);
+
+      rli->bitpos = round_up (rli->bitpos, type_align);
+    }
+#endif
+
   /* Offset so far becomes the position of this field after normalizing.  */
   normalize_rli (rli);
   DECL_FIELD_OFFSET (field) = rli->offset;
@@ -950,6 +1009,8 @@ place_field (rli, field)
       rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, DECL_SIZE (field));
       normalize_rli (rli);
     }
+
+  rli->prev_field = field;
 }
 
 /* Assuming that all the fields have been laid out, this function uses

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]