This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[pre-patch] Re: changing struct bitfield allocation ?
- From: DJ Delorie <dj at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 25 Jul 2003 20:14:50 -0400
- Subject: [pre-patch] Re: changing struct bitfield allocation ?
- References: <200307250048.h6P0mNe26423@greed.delorie.com>
I wrote on gcc@ :
> GCC currently allocates bits for bitfields starting at the lowest
> addressed byte of the bytes allocated to the type (i.e. the LSB for
> little endian, MSB for big endian, but I need them to be allocated
> from the MSB always, at least if the structure has a certain attribute
> set.
Ok, nothing we already had supported this, so I patched it. It calls
for a new target hook. A patch preview is attached, as is pre-docs
for the target hook (I.e. I'll pretty it up once the general idea is
approved ;) How does this look?
/* Return true if bitfields in RECORD_TYPE should be allocated
within their base type's bytes starting at the opposite end. */
bool (* reverse_bitfield_layout_p) (tree record_type);
bool TARGET_REVERSE_BITFIELD_LAYOUT_P (tree record_type);
This predicate indicates if bitfields within record_type should be
allocated from the "other end" of their base types. In other words,
the first int-typed bitfield in a struct would be at the LSB of
its int on MSB systems, and at the MSB of its int on LSB systems.
Consider this example:
union {
struct {
int a:8;
int b:8;
int c:8;
int d:8;
} f;
int i;
char c[4];
} foo;
GCC would normally lay out the bitfields (f.a, etc) such that f.a
and c[0] shared the same byte in memory. This would correspond to
the LSB of foo.i on an LSB system, and the MSB of foo.i on an MSB
system.
If this predicate returns true, the layout is altered such that f.a
and c[3] share the same byte in memory. Note that, by if this
predicate is sensitive to the endianness of the target, the
structures will be laid out with f.a always in the MSB or always in
the LSB.
Note that this predicate requires that the
TARGET_MS_BITFIELD_LAYOUT_P predicate return true, and that the
record_type is not packed, to ensure that differing base types do
not overlap within the bitfield allocation.
Index: stor-layout.c
===================================================================
RCS file: /cvs/uberbaum/gcc/stor-layout.c,v
retrieving revision 1.161
diff -p -2 -r1.161 stor-layout.c
*** stor-layout.c 13 Jul 2003 17:12:28 -0000 1.161
--- stor-layout.c 25 Jul 2003 23:22:40 -0000
*************** finalize_type_size (tree type)
*** 1436,1439 ****
--- 1436,1462 ----
}
+ static void
+ reverse_bitfield_layout (record_layout_info rli)
+ {
+ tree field, oldtype;
+ if (! lookup_attribute ("renesas", TYPE_ATTRIBUTES (rli->t)))
+ return;
+ for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field))
+ {
+ tree type = TREE_TYPE (field);
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
+ return;
+ oldtype = TREE_TYPE (DECL_FIELD_BIT_OFFSET (field));
+ DECL_FIELD_BIT_OFFSET (field)
+ = size_binop (MINUS_EXPR,
+ size_binop (MINUS_EXPR, TYPE_SIZE (type),
+ DECL_SIZE (field)),
+ DECL_FIELD_BIT_OFFSET (field));
+ TREE_TYPE (DECL_FIELD_BIT_OFFSET (field)) = oldtype;
+ }
+ }
+
/* Do all of the work required to layout the type indicated by RLI,
once the fields have been laid out. This function will call `free'
*************** void
*** 1445,1448 ****
--- 1468,1476 ----
finish_record_layout (record_layout_info rli, int free_p)
{
+ if ((* targetm.ms_bitfield_layout_p) (rli->t)
+ && (* targetm.reverse_bitfield_layout_p) (rli->t)
+ && ! TYPE_PACKED (rli->t))
+ reverse_bitfield_layout (rli);
+
/* Compute the final size. */
finalize_record_size (rli);