mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-25 16:50:49 +08:00
tree.h (categorize_ctor_elements): Adjust prototype and add descriptive comment...
* 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. * gnat.dg/outer_agg_bitfield_constructor.adb: New test. * gnat.dg/nested_agg_bitfield_constructor.adb: New test. From-SVN: r115553
This commit is contained in:
parent
57255173da
commit
fe24d4852e
@ -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.
|
||||
|
72
gcc/expr.c
72
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
34
gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb
Normal file
34
gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb
Normal file
@ -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;
|
44
gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb
Normal file
44
gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb
Normal file
@ -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;
|
||||
|
||||
|
16
gcc/tree.h
16
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. */
|
||||
|
19
gcc/varasm.c
19
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user