aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/expr.c72
-rw-r--r--gcc/gimplify.c17
-rw-r--r--gcc/output.h7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb34
-rw-r--r--gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb44
-rw-r--r--gcc/tree.h16
-rw-r--r--gcc/varasm.c19
9 files changed, 197 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5cc02be..558765d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2006-07-18 Olivier Hainque <hainque@adacore.com>
+
+ * tree.h (categorize_ctor_elements): Adjust prototype and add
+ descriptive comment, both in accordance with the interface change
+ described below.
+ * varasm.c (constructor_static_from_elts_p): New function.
+ Whether a constructor node is a valid static constant initializer
+ if all its elements are.
+ (initializer_constant_valid_p) <CONSTRUCTOR value>: Use it.
+ * output.h: Declare it.
+ * expr.c (categorize_ctor_elements_1): Return whether the constructor
+ is a valid constant initializer instead of computing the number of
+ non-constant elements. Use constructor_static_from_elts_p for this
+ purpose. Replace the head comment with an indication that this is a
+ helper for categorize_ctor_elements.
+ (categorize_ctor_elements): Same interface change as for the _1
+ helper. Former head comment from this helper moved here, adjusted to
+ account for the interface changes.
+ (mostly_zeros_p): Adjust call to categorize_ctor_elements.
+ (all_zeros_p): Likewise.
+ * gimplify.c (gimplify_init_constructor): Decide whether we can make
+ static versions of the constructor from the categorize_ctor_elements
+ return value instead of the formerly computed number of non-constant
+ elements.
+
2006-07-18 Paolo Bonzini <bonzini@gnu.org>
* configure: Regenerate.
diff --git a/gcc/expr.c b/gcc/expr.c
index e46e3e7..48ec0ef 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4531,28 +4531,24 @@ store_expr (tree exp, rtx target, int call_param_p)
return NULL_RTX;
}
-/* Examine CTOR to discover:
- * how many scalar fields are set to nonzero values,
- and place it in *P_NZ_ELTS;
- * how many scalar fields are set to non-constant values,
- and place it in *P_NC_ELTS; and
- * how many scalar fields in total are in CTOR,
- and place it in *P_ELT_COUNT.
- * if a type is a union, and the initializer from the constructor
- is not the largest element in the union, then set *p_must_clear. */
+/* Helper for categorize_ctor_elements. Identical interface. */
-static void
+static bool
categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
- HOST_WIDE_INT *p_nc_elts,
HOST_WIDE_INT *p_elt_count,
bool *p_must_clear)
{
unsigned HOST_WIDE_INT idx;
- HOST_WIDE_INT nz_elts, nc_elts, elt_count;
+ HOST_WIDE_INT nz_elts, elt_count;
tree value, purpose;
+ /* Whether CTOR is a valid constant initializer, in accordance with what
+ initializer_constant_valid_p does. If inferred from the constructor
+ elements, true until proven otherwise. */
+ bool const_from_elts_p = constructor_static_from_elts_p (ctor);
+ bool const_p = const_from_elts_p ? true : TREE_STATIC (ctor);
+
nz_elts = 0;
- nc_elts = 0;
elt_count = 0;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value)
@@ -4574,11 +4570,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
{
case CONSTRUCTOR:
{
- HOST_WIDE_INT nz = 0, nc = 0, ic = 0;
- categorize_ctor_elements_1 (value, &nz, &nc, &ic, p_must_clear);
+ HOST_WIDE_INT nz = 0, ic = 0;
+
+ bool const_elt_p
+ = categorize_ctor_elements_1 (value, &nz, &ic, p_must_clear);
+
nz_elts += mult * nz;
- nc_elts += mult * nc;
- elt_count += mult * ic;
+ elt_count += mult * ic;
+
+ if (const_from_elts_p && const_p)
+ const_p = const_elt_p;
}
break;
@@ -4617,8 +4618,10 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
default:
nz_elts += mult;
elt_count += mult;
- if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
- nc_elts += mult;
+
+ if (const_from_elts_p && const_p)
+ const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
+ != NULL_TREE;
break;
}
}
@@ -4660,22 +4663,33 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
}
*p_nz_elts += nz_elts;
- *p_nc_elts += nc_elts;
*p_elt_count += elt_count;
+
+ return const_p;
}
-void
+/* Examine CTOR to discover:
+ * how many scalar fields are set to nonzero values,
+ and place it in *P_NZ_ELTS;
+ * how many scalar fields in total are in CTOR,
+ and place it in *P_ELT_COUNT.
+ * if a type is a union, and the initializer from the constructor
+ is not the largest element in the union, then set *p_must_clear.
+
+ Return whether or not CTOR is a valid static constant initializer, the same
+ as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */
+
+bool
categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
- HOST_WIDE_INT *p_nc_elts,
HOST_WIDE_INT *p_elt_count,
bool *p_must_clear)
{
*p_nz_elts = 0;
- *p_nc_elts = 0;
*p_elt_count = 0;
*p_must_clear = false;
- categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count,
- p_must_clear);
+
+ return
+ categorize_ctor_elements_1 (ctor, p_nz_elts, p_elt_count, p_must_clear);
}
/* Count the number of scalars in TYPE. Return -1 on overflow or
@@ -4777,10 +4791,10 @@ mostly_zeros_p (tree exp)
if (TREE_CODE (exp) == CONSTRUCTOR)
{
- HOST_WIDE_INT nz_elts, nc_elts, count, elts;
+ HOST_WIDE_INT nz_elts, count, elts;
bool must_clear;
- categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear);
+ categorize_ctor_elements (exp, &nz_elts, &count, &must_clear);
if (must_clear)
return 1;
@@ -4800,10 +4814,10 @@ all_zeros_p (tree exp)
if (TREE_CODE (exp) == CONSTRUCTOR)
{
- HOST_WIDE_INT nz_elts, nc_elts, count;
+ HOST_WIDE_INT nz_elts, count;
bool must_clear;
- categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear);
+ categorize_ctor_elements (exp, &nz_elts, &count, &must_clear);
return nz_elts == 0;
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index a5e7e66..16e4d3c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2940,8 +2940,8 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
{
struct gimplify_init_ctor_preeval_data preeval_data;
HOST_WIDE_INT num_type_elements, num_ctor_elements;
- HOST_WIDE_INT num_nonzero_elements, num_nonconstant_elements;
- bool cleared;
+ HOST_WIDE_INT num_nonzero_elements;
+ bool cleared, valid_const_initializer;
/* Aggregate types must lower constructors to initialization of
individual elements. The exception is that a CONSTRUCTOR node
@@ -2949,13 +2949,16 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
if (VEC_empty (constructor_elt, elts))
break;
- categorize_ctor_elements (ctor, &num_nonzero_elements,
- &num_nonconstant_elements,
- &num_ctor_elements, &cleared);
+ /* Fetch information about the constructor to direct later processing.
+ We might want to make static versions of it in various cases, and
+ can only do so if it known to be a valid constant initializer. */
+ valid_const_initializer
+ = categorize_ctor_elements (ctor, &num_nonzero_elements,
+ &num_ctor_elements, &cleared);
/* If a const aggregate variable is being initialized, then it
should never be a lose to promote the variable to be static. */
- if (num_nonconstant_elements == 0
+ if (valid_const_initializer
&& num_nonzero_elements > 1
&& TREE_READONLY (object)
&& TREE_CODE (object) == VAR_DECL)
@@ -3012,7 +3015,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
for sparse arrays, though, as it's more efficient to follow
the standard CONSTRUCTOR behavior of memset followed by
individual element initialization. */
- if (num_nonconstant_elements == 0 && !cleared)
+ if (valid_const_initializer && !cleared)
{
HOST_WIDE_INT size = int_size_in_bytes (type);
unsigned int align;
diff --git a/gcc/output.h b/gcc/output.h
index 6d518c4..3cfe32c 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -280,6 +280,13 @@ extern void output_shared_constant_pool (void);
extern void output_object_blocks (void);
+/* Whether a constructor CTOR is a valid static constant initializer if all
+ its elements are. This used to be internal to initializer_constant_valid_p
+ and has been exposed to let other functions like categorize_ctor_elements
+ evaluate the property while walking a constructor for other purposes. */
+
+extern bool constructor_static_from_elts_p (tree);
+
/* Return nonzero if VALUE is a valid constant-valued expression
for use in initializing a static variable; one that can be an
element of a "constant" initializer.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0828f4a..f73f2e6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-07-18 Olivier Hainque <hainque@adacore.com>
+
+ * gnat.dg/outer_agg_bitfield_constructor.adb: New test.
+ * gnat.dg/nested_agg_bitfield_constructor.adb: New test.
+
2006-07-18 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c/28286
diff --git a/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb b/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb
new file mode 100644
index 0000000..6015900
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb
@@ -0,0 +1,34 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+-- (bits of "Header" unused)
+
+procedure Nested_Agg_Bitfield_Constructor is
+
+ type Uint64 is mod 2 ** 64;
+ type Uint16 is mod 2 ** 16;
+
+ type Time_Stamp is record
+ Sec : Uint64;
+ Year : Uint16;
+ end record;
+
+ type Msg_Header is record
+ Stamp : Time_Stamp;
+ end record;
+ for Msg_Header use record
+ Stamp at 0 range 0 .. 64+16-1;
+ end record;
+ for Msg_Header'Size use 80;
+
+ type Msg is record
+ Header : Msg_Header;
+ end record;
+
+ for Msg use record
+ Header at 0 range 0 .. 191;
+ end record;
+
+ M : Msg := (Header => (Stamp => (2, 4)));
+begin
+ null;
+end;
diff --git a/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb b/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb
new file mode 100644
index 0000000..6658042
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+procedure Outer_Agg_Bitfield_Constructor is
+
+ type Mod_64 is mod 2 ** 64;
+ for Mod_64'Size use 64;
+
+ type Uint_16 is range 0 .. 2 ** 16 - 1;
+ for Uint_16'Size use 16;
+
+ type Values_Type is record
+ M64 : Mod_64;
+ U16 : Uint_16;
+ end record;
+
+ for Values_Type use record
+ M64 at 0 range 0 .. 63;
+ U16 at 8 range 0 .. 15;
+ end record;
+
+ type Wrapper_Type is record
+ Values : Values_Type;
+ end record;
+
+ for Wrapper_Type use record
+ Values at 0 range 0 .. 79;
+ end record;
+
+ M : constant := 2;
+ U : constant := 4;
+
+ W : Wrapper_Type := (Values => (M, U));
+
+ procedure Check (O : Wrapper_Type) is
+ begin
+ if O.Values.M64 /= M or else O.Values.U16 /= U then
+ raise Program_Error;
+ end if;
+ end;
+begin
+ Check (W);
+end;
+
+
diff --git a/gcc/tree.h b/gcc/tree.h
index 12e2f59..dfea92a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3924,8 +3924,20 @@ extern int fields_length (tree);
extern bool initializer_zerop (tree);
-extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
- HOST_WIDE_INT *, bool *);
+/* Examine CTOR to discover:
+ * how many scalar fields are set to nonzero values,
+ and place it in *P_NZ_ELTS;
+ * how many scalar fields in total are in CTOR,
+ and place it in *P_ELT_COUNT.
+ * if a type is a union, and the initializer from the constructor
+ is not the largest element in the union, then set *p_must_clear.
+
+ Return whether or not CTOR is a valid static constant initializer, the same
+ as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */
+
+extern bool categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
+ bool *);
+
extern HOST_WIDE_INT count_type_elements (tree, bool);
/* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9dcc3b4..1f5f43a 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -3699,6 +3699,20 @@ output_addressed_constants (tree exp)
}
}
+/* Whether a constructor CTOR is a valid static constant initializer if all
+ its elements are. This used to be internal to initializer_constant_valid_p
+ and has been exposed to let other functions like categorize_ctor_elements
+ evaluate the property while walking a constructor for other purposes. */
+
+bool
+constructor_static_from_elts_p (tree ctor)
+{
+ return (TREE_CONSTANT (ctor)
+ && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
+ || TREE_CODE (TREE_TYPE (ctor)) == RECORD_TYPE)
+ && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
+}
+
/* Return nonzero if VALUE is a valid constant-valued expression
for use in initializing a static variable; one that can be an
element of a "constant" initializer.
@@ -3719,10 +3733,7 @@ initializer_constant_valid_p (tree value, tree endtype)
switch (TREE_CODE (value))
{
case CONSTRUCTOR:
- if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
- && TREE_CONSTANT (value)
- && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value)))
+ if (constructor_static_from_elts_p (value))
{
unsigned HOST_WIDE_INT idx;
tree elt;