Hi,
in Ada types can be very dynamic: not only can their shape depend on variables
but it can also depend on the object itself (these are called self-referential
types). This raises interesting compile-time issues when you have dozens of
dynamic fields in a record type, or dozens of nested dynamic record types, as
every offset or size calculation is a fully-fledged expression in the GENERIC
language and they can quickly add up if you are not careful.
This is dealt with in stor-layout.c by means of the variable_size function,
which ensures that these expressions are evaluated only once instead of being
duplicated again and again as the complexity grows up. The problem is that it
is only called for size expressions (DECL_SIZE and DECL_SIZE_UNIT), which is
fine for nested types, but not for offsets, which means that you will have a
memory explosion for flat types with dozens of consecutive dynamic fields.
The patch plugs the hole by invoking it for DECL_FIELD_OFFSET as well (and the
effect is spectacular for pathological cases). Tested on x86_64-suse-linux,
although this will essentially only affect Ada. OK for the mainline?
2014-04-14 Eric Botcazou <ebotca...@adacore.com>
* stor-layout.c (place_field): Finalize non-constant offset for the
field, if any.
--
Eric Botcazou
Index: stor-layout.c
===================================================================
--- stor-layout.c (revision 209334)
+++ stor-layout.c (working copy)
@@ -1417,6 +1417,10 @@ place_field (record_layout_info rli, tre
DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
+ /* Evaluate nonconstant offsets only once, either now or as soon as safe. */
+ if (TREE_CODE (DECL_FIELD_OFFSET (field)) != INTEGER_CST)
+ DECL_FIELD_OFFSET (field) = variable_size (DECL_FIELD_OFFSET (field));
+
/* If this field ended up more aligned than we thought it would be (we
approximate this by seeing if its position changed), lay out the field
again; perhaps we can use an integral mode for it now. */