This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: continue breaking out layout code
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH: continue breaking out layout code
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Tue, 14 Mar 2000 16:19:02 -0800
- Reply-to: mark at codesourcery dot com
This patch is analagous to my previous patch to breakout layout_type
into component functions that could be called by front-ends: this
patch does the same thing for unions. The breakout also allowed a
little more sharing between the union-layout and record-layout code.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ChangeLog,v
retrieving revision 1.5918
diff -c -p -r1.5918 ChangeLog
*** ChangeLog 2000/03/13 19:35:38 1.5918
--- ChangeLog 2000/03/14 23:02:59
***************
*** 1,3 ****
--- 1,13 ----
+ 2000-03-14 Mark Mitchell <mark@codesourcery.com>
+
+ * stor-layout.c (layout_union): Remove.
+ (layout_union_field): New function, split out from layout_union.
+ (finish_union_layout): Likewise.
+ (layout_field): Handle unions by calling layout_union_field.
+ (finish_record_layout): Handle unions.
+ (layout_type): Combine RECORD_TYPE, UNION_TYPE, and
+ QUAL_UNION_TYPE handling.
+
2000-03-13 Bernd Schmidt <bernds@cygnus.co.uk>
* stmt.c (expand_end_case): RANGE may be signed, and when checking
Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stor-layout.c,v
retrieving revision 1.55
diff -c -p -r1.55 stor-layout.c
*** stor-layout.c 2000/03/13 13:24:54 1.55
--- stor-layout.c 2000/03/14 23:03:00
*************** unsigned int maximum_field_alignment;
*** 50,59 ****
May be overridden by front-ends. */
unsigned int set_alignment = 0;
- static void layout_union PARAMS ((tree));
static void finalize_record_size PARAMS ((record_layout_info));
static void compute_record_mode PARAMS ((tree));
static void finalize_type_size PARAMS ((tree));
/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */
--- 50,60 ----
May be overridden by front-ends. */
unsigned int set_alignment = 0;
static void finalize_record_size PARAMS ((record_layout_info));
static void compute_record_mode PARAMS ((tree));
static void finalize_type_size PARAMS ((tree));
+ static void layout_union_field PARAMS ((record_layout_info, tree));
+ static void finish_union_layout PARAMS ((record_layout_info));
/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */
*************** layout_decl (decl, known_align)
*** 402,410 ****
}
}
! /* Create a new record_layout_info for the RECORD_TYPE T. It is the
! responsibility of the caller to call `free' for the storage the
! returned. */
record_layout_info
new_record_layout_info (t)
--- 403,411 ----
}
}
! /* Create a new record_layout_info for T, which may be a RECORD_TYPE,
! UNION_TYPE, or QUAL_UNION_TYPE. It is the responsibility of the
! caller to call `free' for the storage the returned. */
record_layout_info
new_record_layout_info (t)
*************** new_record_layout_info (t)
*** 429,434 ****
--- 430,494 ----
return rli;
}
+ /* Like layout_field, but for unions. */
+
+ static void
+ layout_union_field (rli, field)
+ record_layout_info rli;
+ tree field;
+ {
+ tree dsize;
+
+ /* This function should only be used for unions; use layout_field
+ for RECORD_TYPEs. */
+ if (TREE_CODE (rli->t) != UNION_TYPE
+ && TREE_CODE (rli->t) != QUAL_UNION_TYPE)
+ abort ();
+
+ /* By now, we should only be seeing FIELD_DECLs. */
+ if (TREE_CODE (field) != FIELD_DECL)
+ abort ();
+
+ layout_decl (field, 0);
+ DECL_FIELD_BITPOS (field) = bitsize_int (0);
+
+ /* Union must be at least as aligned as any field requires. */
+ rli->record_align = MAX (rli->record_align, DECL_ALIGN (field));
+
+ #ifdef PCC_BITFIELD_TYPE_MATTERS
+ /* On the m88000, a bit field of declare type `int' forces the
+ entire union to have `int' alignment. */
+ if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
+ rli->record_align = MAX (rli->record_align,
+ TYPE_ALIGN (TREE_TYPE (field)));
+ #endif
+
+ dsize = DECL_SIZE (field);
+ if (TREE_CODE (rli->t) == UNION_TYPE)
+ {
+ /* Set union_size to max (decl_size, union_size). There are
+ more and less general ways to do this. Use only CONST_SIZE
+ unless forced to use VAR_SIZE. */
+
+ if (TREE_CODE (dsize) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (dsize)
+ && TREE_INT_CST_HIGH (dsize) == 0)
+ rli->const_size
+ = MAX (rli->const_size, TREE_INT_CST_LOW (dsize));
+ else if (rli->var_size == 0)
+ rli->var_size = dsize;
+ else
+ rli->var_size = size_binop (MAX_EXPR, rli->var_size, dsize);
+ }
+ else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
+ rli->var_size = fold (build (COND_EXPR, bitsizetype,
+ DECL_QUALIFIER (field),
+ DECL_SIZE (field),
+ (rli->var_size
+ ? rli->var_size
+ : bitsize_int (0))));
+ }
+
/* RLI contains information about the layout of a RECORD_TYPE. FIELD
is a FIELD_DECL to be added after those fields already present in
T. (FIELD is not actually added to the TYPE_FIELDS list here;
*************** layout_field (rli, field)
*** 463,468 ****
--- 523,535 ----
be laid out. Likewise for initialized constant fields. */
else if (TREE_CODE (field) != FIELD_DECL)
return;
+ /* This function should only be used for records; use
+ layout_union_field for unions. */
+ else if (TREE_CODE (rli->t) != RECORD_TYPE)
+ {
+ layout_union_field (rli, field);
+ return;
+ }
/* Work out the known alignment so far. */
known_align = rli->var_size ? rli->var_align : rli->const_size;
*************** void
*** 931,940 ****
finish_record_layout (rli)
record_layout_info rli;
{
! /* Compute the final size. */
! finalize_record_size (rli);
! /* Compute the TYPE_MODE for the record. */
! compute_record_mode (rli->t);
/* Lay out any static members. This is done now because their type
may use the record's type. */
while (rli->pending_statics)
--- 998,1014 ----
finish_record_layout (rli)
record_layout_info rli;
{
! /* Use finish_union_layout for unions. */
! if (TREE_CODE (rli->t) != RECORD_TYPE)
! finish_union_layout (rli);
! else
! {
! /* Compute the final size. */
! finalize_record_size (rli);
! /* Compute the TYPE_MODE for the record. */
! compute_record_mode (rli->t);
! }
!
/* Lay out any static members. This is done now because their type
may use the record's type. */
while (rli->pending_statics)
*************** finish_record_layout (rli)
*** 942,1059 ****
layout_decl (TREE_VALUE (rli->pending_statics), 0);
rli->pending_statics = TREE_CHAIN (rli->pending_statics);
}
/* Perform any last tweaks to the TYPE_SIZE, etc. */
finalize_type_size (rli->t);
/* Clean up. */
free (rli);
}
!
! /* Lay out a UNION_TYPE or QUAL_UNION_TYPE type.
! Lay out all the fields, set their positions to zero,
! and compute the size and alignment of the union (maximum of any field).
! Note that if you set the TYPE_ALIGN before calling this
! then the union align is aligned to at least that boundary. */
static void
! layout_union (rec)
! tree rec;
{
! register tree field;
! unsigned int union_align = BITS_PER_UNIT;
!
! /* The size of the union, based on the fields scanned so far,
! is max (CONST_SIZE, VAR_SIZE).
! VAR_SIZE may be null; then CONST_SIZE by itself is the size. */
! unsigned HOST_WIDE_INT const_size = 0;
! register tree var_size = 0;
!
! #ifdef STRUCTURE_SIZE_BOUNDARY
! /* Packed structures don't need to have minimum size. */
! if (! TYPE_PACKED (rec))
! union_align = STRUCTURE_SIZE_BOUNDARY;
! #endif
!
! /* If this is a QUAL_UNION_TYPE, we want to process the fields in
! the reverse order in building the COND_EXPR that denotes its
! size. We reverse them again later. */
! if (TREE_CODE (rec) == QUAL_UNION_TYPE)
! TYPE_FIELDS (rec) = nreverse (TYPE_FIELDS (rec));
!
! for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))
! {
! tree dsize;
!
! /* Enums which are local to this class need not be laid out. */
! if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL)
! continue;
!
! layout_decl (field, 0);
! DECL_FIELD_BITPOS (field) = bitsize_int (0);
!
! /* Union must be at least as aligned as any field requires. */
!
! union_align = MAX (union_align, DECL_ALIGN (field));
!
! #ifdef PCC_BITFIELD_TYPE_MATTERS
! /* On the m88000, a bit field of declare type `int'
! forces the entire union to have `int' alignment. */
! if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
! union_align = MAX (union_align, TYPE_ALIGN (TREE_TYPE (field)));
! #endif
!
! dsize = DECL_SIZE (field);
! if (TREE_CODE (rec) == UNION_TYPE)
! {
! /* Set union_size to max (decl_size, union_size).
! There are more and less general ways to do this.
! Use only CONST_SIZE unless forced to use VAR_SIZE. */
!
! if (TREE_CODE (dsize) == INTEGER_CST
! && ! TREE_CONSTANT_OVERFLOW (dsize)
! && TREE_INT_CST_HIGH (dsize) == 0)
! const_size
! = MAX (const_size, TREE_INT_CST_LOW (dsize));
! else if (var_size == 0)
! var_size = dsize;
! else
! var_size = size_binop (MAX_EXPR, var_size, dsize);
! }
! else if (TREE_CODE (rec) == QUAL_UNION_TYPE)
! var_size = fold (build (COND_EXPR, bitsizetype, DECL_QUALIFIER (field),
! DECL_SIZE (field),
! var_size ? var_size : bitsize_int (0)));
! }
!
! if (TREE_CODE (rec) == QUAL_UNION_TYPE)
! TYPE_FIELDS (rec) = nreverse (TYPE_FIELDS (rec));
/* Determine the ultimate size of the union (in bytes). */
! if (NULL == var_size)
! TYPE_SIZE (rec)
! = bitsize_int (CEIL (const_size, BITS_PER_UNIT) * BITS_PER_UNIT);
! else if (const_size == 0)
! TYPE_SIZE (rec) = var_size;
else
! TYPE_SIZE (rec) = size_binop (MAX_EXPR, var_size,
! round_up (bitsize_int (const_size),
! BITS_PER_UNIT));
/* Determine the desired alignment. */
#ifdef ROUND_TYPE_ALIGN
! TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), union_align);
#else
! TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), union_align);
#endif
#ifdef ROUND_TYPE_SIZE
! TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));
#else
/* Round the size up to be a multiple of the required alignment */
! TYPE_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));
#endif
}
/* Calculate the mode, size, and alignment for TYPE.
For an array type, calculate the element separation as well.
--- 1016,1101 ----
layout_decl (TREE_VALUE (rli->pending_statics), 0);
rli->pending_statics = TREE_CHAIN (rli->pending_statics);
}
+
/* Perform any last tweaks to the TYPE_SIZE, etc. */
finalize_type_size (rli->t);
/* Clean up. */
free (rli);
}
! /* Like finish_record_layout, but for unions. */
static void
! finish_union_layout (rli)
! record_layout_info rli;
{
! /* This function should only be used for unions; use
! finish_record_layout for RECORD_TYPEs. */
! if (TREE_CODE (rli->t) != UNION_TYPE
! && TREE_CODE (rli->t) != QUAL_UNION_TYPE)
! abort ();
/* Determine the ultimate size of the union (in bytes). */
! if (NULL == rli->var_size)
! TYPE_SIZE (rli->t)
! = bitsize_int (CEIL (rli->const_size, BITS_PER_UNIT) * BITS_PER_UNIT);
! else if (rli->const_size == 0)
! TYPE_SIZE (rli->t) = rli->var_size;
else
! TYPE_SIZE (rli->t) = size_binop (MAX_EXPR, rli->var_size,
! round_up (bitsize_int (rli->const_size),
! BITS_PER_UNIT));
/* Determine the desired alignment. */
#ifdef ROUND_TYPE_ALIGN
! TYPE_ALIGN (rli->t) = ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
! rli->record_align);
#else
! TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
#endif
#ifdef ROUND_TYPE_SIZE
! TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, TYPE_SIZE (rli->t),
! TYPE_ALIGN (rli->t));
#else
/* Round the size up to be a multiple of the required alignment */
! TYPE_SIZE (rli->t) = round_up (TYPE_SIZE (rli->t),
! TYPE_ALIGN (rli->t));
#endif
+
+ TYPE_MODE (rli->t) = BLKmode;
+ if (TREE_CODE (TYPE_SIZE (rli->t)) == INTEGER_CST
+ /* If structure's known alignment is less than
+ what the scalar mode would need, and it matters,
+ then stick with BLKmode. */
+ && (! STRICT_ALIGNMENT
+ || TYPE_ALIGN (rli->t) >= BIGGEST_ALIGNMENT
+ || compare_tree_int (TYPE_SIZE (rli->t),
+ TYPE_ALIGN (rli->t)) <= 0))
+ {
+ tree field;
+
+ /* A union which has any BLKmode members must itself be BLKmode;
+ it can't go in a register.
+ Unless the member is BLKmode only because it isn't aligned. */
+ for (field = TYPE_FIELDS (rli->t);
+ field;
+ field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
+ && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
+ return;
+ }
+
+ TYPE_MODE (rli->t)
+ = mode_for_size_tree (TYPE_SIZE (rli->t), MODE_INT, 1);
+ }
}
+
/* Calculate the mode, size, and alignment for TYPE.
For an array type, calculate the element separation as well.
*************** layout_type (type)
*** 1287,1340 ****
}
case RECORD_TYPE:
{
tree field;
record_layout_info rli;
/* Initialize the layout information. */
rli = new_record_layout_info (type);
/* Layout all the fields. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
layout_field (rli, field);
/* Finish laying out the record. */
finish_record_layout (rli);
}
break;
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- layout_union (type);
- TYPE_MODE (type) = BLKmode;
- if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- /* If structure's known alignment is less than
- what the scalar mode would need, and it matters,
- then stick with BLKmode. */
- && (! STRICT_ALIGNMENT
- || TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
- || compare_tree_int (TYPE_SIZE (type), TYPE_ALIGN (type)) <= 0))
- {
- tree field;
-
- /* A union which has any BLKmode members must itself be BLKmode;
- it can't go in a register.
- Unless the member is BLKmode only because it isn't aligned. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
- && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
- goto union_lose;
- }
-
- TYPE_MODE (type)
- = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
-
- union_lose: ;
- }
- break;
-
case SET_TYPE: /* Used by Chill and Pascal. */
if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)
--- 1329,1357 ----
}
case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
{
tree field;
record_layout_info rli;
/* Initialize the layout information. */
rli = new_record_layout_info (type);
+ /* If this is a QUAL_UNION_TYPE, we want to process the fields
+ in the reverse order in building the COND_EXPR that denotes
+ its size. We reverse them again later. */
+ if (TREE_CODE (type) == QUAL_UNION_TYPE)
+ TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
/* Layout all the fields. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
layout_field (rli, field);
+ if (TREE_CODE (type) == QUAL_UNION_TYPE)
+ TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
/* Finish laying out the record. */
finish_record_layout (rli);
}
break;
case SET_TYPE: /* Used by Chill and Pascal. */
if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)
*************** layout_type (type)
*** 1376,1383 ****
}
/* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE. For
! RECORD_TYPEs, finish_record_layout already called this function. */
! if (TREE_CODE (type) != RECORD_TYPE)
finalize_type_size (type);
pop_obstacks ();
--- 1393,1403 ----
}
/* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE. For
! records and unions, finish_record_layout already called this
! function. */
! if (TREE_CODE (type) != RECORD_TYPE
! && TREE_CODE (type) != UNION_TYPE
! && TREE_CODE (type) != QUAL_UNION_TYPE)
finalize_type_size (type);
pop_obstacks ();