Commit cb3d597d by Eric Botcazou Committed by Eric Botcazou

gimple.c (walk_gimple_op): Do not request a pure rvalue on the RHS if the LHS is…

gimple.c (walk_gimple_op): Do not request a pure rvalue on the RHS if the LHS is of a non-renamable type.

	* gimple.c (walk_gimple_op) <GIMPLE_ASSIGN>: Do not request a pure
	rvalue on the RHS if the LHS is of a non-renamable type.
	* tree-ssa-ccp.c (maybe_fold_offset_to_component_ref): Fold result.
ada/
	* gcc-interface/ada-tree.h (TYPE_BY_REFERENCE_P): Delete.
	(DECL_CONST_ADDRESS_P): New macro.
	(SET_DECL_ORIGINAL_FIELD_TO_FIELD): Likewise.
	(SAME_FIELD_P): Likewise.
	* gcc-interface/decl.c (constructor_address_p): New static function.
	(gnat_to_gnu_entity) <object>: Set DECL_CONST_ADDRESS_P according to
	the return value of above function.
	(gnat_to_gnu_entity) <E_Record_Type>: Force BLKmode for all types
	passed by reference.
	<E_Record_Subtype>: Likewise.
	Set TREE_ADDRESSABLE on the type if it passed by reference.
	(make_packable_type): Use SET_DECL_ORIGINAL_FIELD_TO_FIELD.
	(create_field_decl_from): Likewise.
	(substitute_in_type): Likewise.
	(purpose_member_field): Use SAME_FIELD_P.
	* gcc-interface/misc.c (must_pass_by_ref): Test TREE_ADDRESSABLE.
	* gcc-interface/trans.c (lvalue_required_p): Add ADDRESS_OF_CONSTANT
	parameter and adjust recursive calls.
	<N_Explicit_Dereference>: New case.
	<N_Object_Declaration>: Return 1 if the object is of a class-wide type.
	Adjust calls to lvalue_required_p.  Do not return the initializer of a
	DECL_CONST_ADDRESS_P constant if an lvalue is required for it.
	(call_to_gnu): Delay issuing error message for a misaligned actual and
	avoid the associated back-end assertion.  Test TREE_ADDRESSABLE.
	(gnat_gimplify_expr) <ADDR_EXPR>: Handle non-static constructors.
	* gcc-interface/utils.c (make_dummy_type): Set TREE_ADDRESSABLE if the
	type is passed by reference.
	(convert) <CONSTRUCTOR>: Convert in-place in more cases.
	* gcc-interface/utils2.c (build_cond_expr): Drop TYPE_BY_REFERENCE_P.
	(build_simple_component_ref): Use SAME_FIELD_P.

From-SVN: r158254
parent b7e75771
2010-04-13 Eric Botcazou <ebotcazou@adacore.com>
* gimple.c (walk_gimple_op) <GIMPLE_ASSIGN>: Do not request a pure
rvalue on the RHS if the LHS is of a non-renamable type.
* tree-ssa-ccp.c (maybe_fold_offset_to_component_ref): Fold result.
2010-04-13 Matthias Klose <doko@ubuntu.com> 2010-04-13 Matthias Klose <doko@ubuntu.com>
* gcc.c (cc1_options): Handle -iplugindir before processing * gcc.c (cc1_options): Handle -iplugindir before processing
......
2010-04-13 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (TYPE_BY_REFERENCE_P): Delete.
(DECL_CONST_ADDRESS_P): New macro.
(SET_DECL_ORIGINAL_FIELD_TO_FIELD): Likewise.
(SAME_FIELD_P): Likewise.
* gcc-interface/decl.c (constructor_address_p): New static function.
(gnat_to_gnu_entity) <object>: Set DECL_CONST_ADDRESS_P according to
the return value of above function.
(gnat_to_gnu_entity) <E_Record_Type>: Force BLKmode for all types
passed by reference.
<E_Record_Subtype>: Likewise.
Set TREE_ADDRESSABLE on the type if it passed by reference.
(make_packable_type): Use SET_DECL_ORIGINAL_FIELD_TO_FIELD.
(create_field_decl_from): Likewise.
(substitute_in_type): Likewise.
(purpose_member_field): Use SAME_FIELD_P.
* gcc-interface/misc.c (must_pass_by_ref): Test TREE_ADDRESSABLE.
* gcc-interface/trans.c (lvalue_required_p): Add ADDRESS_OF_CONSTANT
parameter and adjust recursive calls.
<N_Explicit_Dereference>: New case.
<N_Object_Declaration>: Return 1 if the object is of a class-wide type.
Adjust calls to lvalue_required_p. Do not return the initializer of a
DECL_CONST_ADDRESS_P constant if an lvalue is required for it.
(call_to_gnu): Delay issuing error message for a misaligned actual and
avoid the associated back-end assertion. Test TREE_ADDRESSABLE.
(gnat_gimplify_expr) <ADDR_EXPR>: Handle non-static constructors.
* gcc-interface/utils.c (make_dummy_type): Set TREE_ADDRESSABLE if the
type is passed by reference.
(convert) <CONSTRUCTOR>: Convert in-place in more cases.
* gcc-interface/utils2.c (build_cond_expr): Drop TYPE_BY_REFERENCE_P.
(build_simple_component_ref): Use SAME_FIELD_P.
2010-04-12 Eric Botcazou <ebotcazou@adacore.com> 2010-04-12 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (Identifier_to_gnu): Use boolean variable. * gcc-interface/trans.c (Identifier_to_gnu): Use boolean variable.
......
...@@ -102,9 +102,6 @@ do { \ ...@@ -102,9 +102,6 @@ do { \
front-end. */ front-end. */
#define TYPE_EXTRA_SUBTYPE_P(NODE) TYPE_LANG_FLAG_2 (NODE) #define TYPE_EXTRA_SUBTYPE_P(NODE) TYPE_LANG_FLAG_2 (NODE)
/* Nonzero for composite types if this is a by-reference type. */
#define TYPE_BY_REFERENCE_P(NODE) TYPE_LANG_FLAG_2 (NODE)
/* For RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE, nonzero if this is the /* For RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE, nonzero if this is the
type for an object whose type includes its template in addition to type for an object whose type includes its template in addition to
its value (only true for RECORD_TYPE). */ its value (only true for RECORD_TYPE). */
...@@ -325,6 +322,10 @@ do { \ ...@@ -325,6 +322,10 @@ do { \
been elaborated and TREE_READONLY is not set on it. */ been elaborated and TREE_READONLY is not set on it. */
#define DECL_READONLY_ONCE_ELAB(NODE) DECL_LANG_FLAG_0 (VAR_DECL_CHECK (NODE)) #define DECL_READONLY_ONCE_ELAB(NODE) DECL_LANG_FLAG_0 (VAR_DECL_CHECK (NODE))
/* Nonzero in a CONST_DECL if its value is (essentially) the address of a
constant CONSTRUCTOR. */
#define DECL_CONST_ADDRESS_P(NODE) DECL_LANG_FLAG_0 (CONST_DECL_CHECK (NODE))
/* Nonzero if this decl is always used by reference; i.e., an INDIRECT_REF /* Nonzero if this decl is always used by reference; i.e., an INDIRECT_REF
is needed to access the object. */ is needed to access the object. */
#define DECL_BY_REF_P(NODE) DECL_LANG_FLAG_1 (NODE) #define DECL_BY_REF_P(NODE) DECL_LANG_FLAG_1 (NODE)
...@@ -369,6 +370,20 @@ do { \ ...@@ -369,6 +370,20 @@ do { \
#define SET_DECL_ORIGINAL_FIELD(NODE, X) \ #define SET_DECL_ORIGINAL_FIELD(NODE, X) \
SET_DECL_LANG_SPECIFIC (FIELD_DECL_CHECK (NODE), X) SET_DECL_LANG_SPECIFIC (FIELD_DECL_CHECK (NODE), X)
/* Set DECL_ORIGINAL_FIELD of FIELD1 to (that of) FIELD2. */
#define SET_DECL_ORIGINAL_FIELD_TO_FIELD(FIELD1, FIELD2) \
SET_DECL_ORIGINAL_FIELD ((FIELD1), \
DECL_ORIGINAL_FIELD (FIELD2) \
? DECL_ORIGINAL_FIELD (FIELD2) : (FIELD2))
/* Return true if FIELD1 and FIELD2 represent the same field. */
#define SAME_FIELD_P(FIELD1, FIELD2) \
((FIELD1) == (FIELD2) \
|| DECL_ORIGINAL_FIELD (FIELD1) == (FIELD2) \
|| (FIELD1) == DECL_ORIGINAL_FIELD (FIELD2) \
|| (DECL_ORIGINAL_FIELD (FIELD1) \
&& (DECL_ORIGINAL_FIELD (FIELD1) == DECL_ORIGINAL_FIELD (FIELD2))))
/* In a VAR_DECL, points to the object being renamed if the VAR_DECL is a /* In a VAR_DECL, points to the object being renamed if the VAR_DECL is a
renaming pointer, otherwise 0. Note that this object is guaranteed to renaming pointer, otherwise 0. Note that this object is guaranteed to
be protected against multiple evaluations. */ be protected against multiple evaluations. */
......
...@@ -138,6 +138,7 @@ static bool same_discriminant_p (Entity_Id, Entity_Id); ...@@ -138,6 +138,7 @@ static bool same_discriminant_p (Entity_Id, Entity_Id);
static bool array_type_has_nonaliased_component (tree, Entity_Id); static bool array_type_has_nonaliased_component (tree, Entity_Id);
static bool compile_time_known_address_p (Node_Id); static bool compile_time_known_address_p (Node_Id);
static bool cannot_be_superflat_p (Node_Id); static bool cannot_be_superflat_p (Node_Id);
static bool constructor_address_p (tree);
static void components_to_record (tree, Node_Id, tree, int, bool, tree *, static void components_to_record (tree, Node_Id, tree, int, bool, tree *,
bool, bool, bool, bool, bool); bool, bool, bool, bool, bool);
static Uint annotate_value (tree); static Uint annotate_value (tree);
...@@ -1376,6 +1377,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -1376,6 +1377,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
DECL_IGNORED_P (gnu_decl) = 1; DECL_IGNORED_P (gnu_decl) = 1;
} }
/* If this is a constant, even if we don't need a true variable, we
may need to avoid returning the initializer in every case. That
can happen for the address of a (constant) constructor because,
upon dereferencing it, the constructor will be reinjected in the
tree, which may not be valid in every case; see lvalue_required_p
for more details. */
if (TREE_CODE (gnu_decl) == CONST_DECL)
DECL_CONST_ADDRESS_P (gnu_decl) = constructor_address_p (gnu_expr);
/* If this is declared in a block that contains a block with an /* If this is declared in a block that contains a block with an
exception handler, we must force this variable in memory to exception handler, we must force this variable in memory to
suppress an invalid optimization. */ suppress an invalid optimization. */
...@@ -2892,10 +2902,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -2892,10 +2902,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
false, all_rep, is_unchecked_union, false, all_rep, is_unchecked_union,
debug_info_p, false); debug_info_p, false);
/* If it is a tagged record force the type to BLKmode to insure that /* If it is passed by reference, force BLKmode to ensure that objects
these objects will always be put in memory. Likewise for limited + of this type will always be put in memory. */
record types. */ if (Is_By_Reference_Type (gnat_entity))
if (Is_Tagged_Type (gnat_entity) || Is_Limited_Record (gnat_entity))
SET_TYPE_MODE (gnu_type, BLKmode); SET_TYPE_MODE (gnu_type, BLKmode);
/* We used to remove the associations of the discriminants and _Parent /* We used to remove the associations of the discriminants and _Parent
...@@ -3216,8 +3225,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3216,8 +3225,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
finish_record_type (gnu_type, gnu_field_list, 2, false); finish_record_type (gnu_type, gnu_field_list, 2, false);
/* See the E_Record_Type case for the rationale. */ /* See the E_Record_Type case for the rationale. */
if (Is_Tagged_Type (gnat_entity) if (Is_By_Reference_Type (gnat_entity))
|| Is_Limited_Record (gnat_entity))
SET_TYPE_MODE (gnu_type, BLKmode); SET_TYPE_MODE (gnu_type, BLKmode);
else else
compute_record_mode (gnu_type); compute_record_mode (gnu_type);
...@@ -4388,8 +4396,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -4388,8 +4396,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|| Is_Class_Wide_Equivalent_Type (gnat_entity)) || Is_Class_Wide_Equivalent_Type (gnat_entity))
TYPE_ALIGN_OK (gnu_type) = 1; TYPE_ALIGN_OK (gnu_type) = 1;
if (AGGREGATE_TYPE_P (gnu_type) && Is_By_Reference_Type (gnat_entity)) /* If the type is passed by reference, objects of this type must be
TYPE_BY_REFERENCE_P (gnu_type) = 1; fully addressable and cannot be copied. */
if (Is_By_Reference_Type (gnat_entity))
TREE_ADDRESSABLE (gnu_type) = 1;
/* ??? Don't set the size for a String_Literal since it is either /* ??? Don't set the size for a String_Literal since it is either
confirming or we don't handle it properly (if the low bound is confirming or we don't handle it properly (if the low bound is
...@@ -5397,6 +5407,20 @@ cannot_be_superflat_p (Node_Id gnat_range) ...@@ -5397,6 +5407,20 @@ cannot_be_superflat_p (Node_Id gnat_range)
return (tree_int_cst_lt (gnu_hb, gnu_lb) == 0); return (tree_int_cst_lt (gnu_hb, gnu_lb) == 0);
} }
/* Return true if GNU_EXPR is (essentially) the address of a CONSTRUCTOR. */
static bool
constructor_address_p (tree gnu_expr)
{
while (TREE_CODE (gnu_expr) == NOP_EXPR
|| TREE_CODE (gnu_expr) == CONVERT_EXPR
|| TREE_CODE (gnu_expr) == NON_LVALUE_EXPR)
gnu_expr = TREE_OPERAND (gnu_expr, 0);
return (TREE_CODE (gnu_expr) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (gnu_expr, 0)) == CONSTRUCTOR);
}
/* Given GNAT_ENTITY, elaborate all expressions that are required to /* Given GNAT_ENTITY, elaborate all expressions that are required to
be elaborated at the point of its definition, but do nothing else. */ be elaborated at the point of its definition, but do nothing else. */
...@@ -6033,10 +6057,7 @@ make_packable_type (tree type, bool in_record) ...@@ -6033,10 +6057,7 @@ make_packable_type (tree type, bool in_record)
!DECL_NONADDRESSABLE_P (old_field)); !DECL_NONADDRESSABLE_P (old_field));
DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field); DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field);
SET_DECL_ORIGINAL_FIELD SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, old_field);
(new_field, (DECL_ORIGINAL_FIELD (old_field)
? DECL_ORIGINAL_FIELD (old_field) : old_field));
if (TREE_CODE (new_type) == QUAL_UNION_TYPE) if (TREE_CODE (new_type) == QUAL_UNION_TYPE)
DECL_QUALIFIER (new_field) = DECL_QUALIFIER (old_field); DECL_QUALIFIER (new_field) = DECL_QUALIFIER (old_field);
...@@ -7253,9 +7274,8 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref) ...@@ -7253,9 +7274,8 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref)
UI_From_Int (TYPE_ALIGN (gnu_type) / BITS_PER_UNIT)); UI_From_Int (TYPE_ALIGN (gnu_type) / BITS_PER_UNIT));
} }
/* Return first element of field list whose TREE_PURPOSE is ELEM or whose /* Return first element of field list whose TREE_PURPOSE is the same as ELEM.
DECL_ORIGINAL_FIELD of TREE_PURPOSE is ELEM. Return NULL_TREE if there Return NULL_TREE if there is no such element in the list. */
is no such element in the list. */
static tree static tree
purpose_member_field (const_tree elem, tree list) purpose_member_field (const_tree elem, tree list)
...@@ -7263,7 +7283,7 @@ purpose_member_field (const_tree elem, tree list) ...@@ -7263,7 +7283,7 @@ purpose_member_field (const_tree elem, tree list)
while (list) while (list)
{ {
tree field = TREE_PURPOSE (list); tree field = TREE_PURPOSE (list);
if (elem == field || elem == DECL_ORIGINAL_FIELD (field)) if (SAME_FIELD_P (field, elem))
return list; return list;
list = TREE_CHAIN (list); list = TREE_CHAIN (list);
} }
...@@ -8035,8 +8055,7 @@ create_field_decl_from (tree old_field, tree field_type, tree record_type, ...@@ -8035,8 +8055,7 @@ create_field_decl_from (tree old_field, tree field_type, tree record_type,
} }
DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field); DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field);
t = DECL_ORIGINAL_FIELD (old_field); SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, old_field);
SET_DECL_ORIGINAL_FIELD (new_field, t ? t : old_field);
DECL_DISCRIMINANT_NUMBER (new_field) = DECL_DISCRIMINANT_NUMBER (old_field); DECL_DISCRIMINANT_NUMBER (new_field) = DECL_DISCRIMINANT_NUMBER (old_field);
TREE_THIS_VOLATILE (new_field) = TREE_THIS_VOLATILE (old_field); TREE_THIS_VOLATILE (new_field) = TREE_THIS_VOLATILE (old_field);
...@@ -8372,9 +8391,7 @@ substitute_in_type (tree t, tree f, tree r) ...@@ -8372,9 +8391,7 @@ substitute_in_type (tree t, tree f, tree r)
} }
DECL_CONTEXT (new_field) = nt; DECL_CONTEXT (new_field) = nt;
SET_DECL_ORIGINAL_FIELD (new_field, SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, field);
(DECL_ORIGINAL_FIELD (field)
? DECL_ORIGINAL_FIELD (field) : field));
TREE_CHAIN (new_field) = TYPE_FIELDS (nt); TREE_CHAIN (new_field) = TYPE_FIELDS (nt);
TYPE_FIELDS (nt) = new_field; TYPE_FIELDS (nt) = new_field;
......
...@@ -700,7 +700,7 @@ must_pass_by_ref (tree gnu_type) ...@@ -700,7 +700,7 @@ must_pass_by_ref (tree gnu_type)
and does not produce compatibility problems with C, since C does and does not produce compatibility problems with C, since C does
not have such objects. */ not have such objects. */
return (TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE return (TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE
|| (AGGREGATE_TYPE_P (gnu_type) && TYPE_BY_REFERENCE_P (gnu_type)) || TREE_ADDRESSABLE (gnu_type)
|| (TYPE_SIZE (gnu_type) || (TYPE_SIZE (gnu_type)
&& TREE_CODE (TYPE_SIZE (gnu_type)) != INTEGER_CST)); && TREE_CODE (TYPE_SIZE (gnu_type)) != INTEGER_CST));
} }
......
...@@ -294,8 +294,8 @@ make_dummy_type (Entity_Id gnat_type) ...@@ -294,8 +294,8 @@ make_dummy_type (Entity_Id gnat_type)
TYPE_DUMMY_P (gnu_type) = 1; TYPE_DUMMY_P (gnu_type) = 1;
TYPE_STUB_DECL (gnu_type) TYPE_STUB_DECL (gnu_type)
= create_type_stub_decl (TYPE_NAME (gnu_type), gnu_type); = create_type_stub_decl (TYPE_NAME (gnu_type), gnu_type);
if (AGGREGATE_TYPE_P (gnu_type) && Is_By_Reference_Type (gnat_type)) if (Is_By_Reference_Type (gnat_type))
TYPE_BY_REFERENCE_P (gnu_type) = 1; TREE_ADDRESSABLE (gnu_type) = 1;
SET_DUMMY_NODE (gnat_underlying, gnu_type); SET_DUMMY_NODE (gnat_underlying, gnu_type);
...@@ -3852,11 +3852,14 @@ convert (tree type, tree expr) ...@@ -3852,11 +3852,14 @@ convert (tree type, tree expr)
return expr; return expr;
} }
/* Likewise for a conversion between original and packable version, but /* Likewise for a conversion between original and packable version, or
we have to work harder in order to preserve type consistency. */ conversion between types of the same size and with the same list of
fields, but we have to work harder to preserve type consistency. */
if (code == ecode if (code == ecode
&& code == RECORD_TYPE && code == RECORD_TYPE
&& TYPE_NAME (type) == TYPE_NAME (etype)) && (TYPE_NAME (type) == TYPE_NAME (etype)
|| tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (etype))))
{ {
VEC(constructor_elt,gc) *e = CONSTRUCTOR_ELTS (expr); VEC(constructor_elt,gc) *e = CONSTRUCTOR_ELTS (expr);
unsigned HOST_WIDE_INT len = VEC_length (constructor_elt, e); unsigned HOST_WIDE_INT len = VEC_length (constructor_elt, e);
...@@ -3871,10 +3874,14 @@ convert (tree type, tree expr) ...@@ -3871,10 +3874,14 @@ convert (tree type, tree expr)
FOR_EACH_CONSTRUCTOR_ELT(e, idx, index, value) FOR_EACH_CONSTRUCTOR_ELT(e, idx, index, value)
{ {
constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); constructor_elt *elt;
/* We expect only simple constructors. Otherwise, punt. */ /* We expect only simple constructors. */
if (!(index == efield || index == DECL_ORIGINAL_FIELD (efield))) if (!SAME_FIELD_P (index, efield))
break;
/* The field must be the same. */
if (!SAME_FIELD_P (efield, field))
break; break;
elt = VEC_quick_push (constructor_elt, v, NULL);
elt->index = field; elt->index = field;
elt->value = convert (TREE_TYPE (field), value); elt->value = convert (TREE_TYPE (field), value);
......
...@@ -1293,10 +1293,9 @@ build_cond_expr (tree result_type, tree condition_operand, ...@@ -1293,10 +1293,9 @@ build_cond_expr (tree result_type, tree condition_operand,
/* If the result type is unconstrained, take the address of the operands and /* If the result type is unconstrained, take the address of the operands and
then dereference the result. Likewise if the result type is passed by then dereference the result. Likewise if the result type is passed by
reference because creating a temporary of this type is not allowed. */ reference, but this is natively handled in the gimplifier. */
if (TREE_CODE (result_type) == UNCONSTRAINED_ARRAY_TYPE if (TREE_CODE (result_type) == UNCONSTRAINED_ARRAY_TYPE
|| CONTAINS_PLACEHOLDER_P (TYPE_SIZE (result_type)) || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (result_type)))
|| (AGGREGATE_TYPE_P (result_type) && TYPE_BY_REFERENCE_P (result_type)))
{ {
result_type = build_pointer_type (result_type); result_type = build_pointer_type (result_type);
true_operand = build_unary_op (ADDR_EXPR, result_type, true_operand); true_operand = build_unary_op (ADDR_EXPR, result_type, true_operand);
...@@ -1588,22 +1587,15 @@ build_simple_component_ref (tree record_variable, tree component, ...@@ -1588,22 +1587,15 @@ build_simple_component_ref (tree record_variable, tree component,
tree new_field; tree new_field;
/* First loop thru normal components. */ /* First loop thru normal components. */
for (new_field = TYPE_FIELDS (record_type); new_field; for (new_field = TYPE_FIELDS (record_type); new_field;
new_field = TREE_CHAIN (new_field)) new_field = TREE_CHAIN (new_field))
if (field == new_field if (SAME_FIELD_P (field, new_field))
|| DECL_ORIGINAL_FIELD (new_field) == field
|| new_field == DECL_ORIGINAL_FIELD (field)
|| (DECL_ORIGINAL_FIELD (field)
&& (DECL_ORIGINAL_FIELD (field)
== DECL_ORIGINAL_FIELD (new_field))))
break; break;
/* Next, loop thru DECL_INTERNAL_P components if we haven't found /* Next, loop thru DECL_INTERNAL_P components if we haven't found
the component in the first search. Doing this search in 2 steps the component in the first search. Doing this search in 2 steps
is required to avoiding hidden homonymous fields in the is required to avoiding hidden homonymous fields in the
_Parent field. */ _Parent field. */
if (!new_field) if (!new_field)
for (new_field = TYPE_FIELDS (record_type); new_field; for (new_field = TYPE_FIELDS (record_type); new_field;
new_field = TREE_CHAIN (new_field)) new_field = TREE_CHAIN (new_field))
......
...@@ -1324,11 +1324,15 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op, ...@@ -1324,11 +1324,15 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
switch (gimple_code (stmt)) switch (gimple_code (stmt))
{ {
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
/* Walk the RHS operands. A formal temporary LHS may use a /* Walk the RHS operands. If the LHS is of a non-renamable type or
COMPONENT_REF RHS. */ is a register variable, we may use a COMPONENT_REF on the RHS. */
if (wi) if (wi)
wi->val_only = !is_gimple_reg (gimple_assign_lhs (stmt)) {
|| !gimple_assign_single_p (stmt); tree lhs = gimple_assign_lhs (stmt);
wi->val_only
= (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
|| !gimple_assign_single_p (stmt);
}
for (i = 1; i < gimple_num_ops (stmt); i++) for (i = 1; i < gimple_num_ops (stmt); i++)
{ {
......
...@@ -1980,7 +1980,7 @@ maybe_fold_offset_to_component_ref (location_t loc, tree record_type, ...@@ -1980,7 +1980,7 @@ maybe_fold_offset_to_component_ref (location_t loc, tree record_type,
if (cmp == 0 if (cmp == 0
&& useless_type_conversion_p (orig_type, field_type)) && useless_type_conversion_p (orig_type, field_type))
{ {
t = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE); t = fold_build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
return t; return t;
} }
...@@ -2004,7 +2004,7 @@ maybe_fold_offset_to_component_ref (location_t loc, tree record_type, ...@@ -2004,7 +2004,7 @@ maybe_fold_offset_to_component_ref (location_t loc, tree record_type,
/* If we matched, then set offset to the displacement into /* If we matched, then set offset to the displacement into
this field. */ this field. */
new_base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE); new_base = fold_build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
SET_EXPR_LOCATION (new_base, loc); SET_EXPR_LOCATION (new_base, loc);
/* Recurse to possibly find the match. */ /* Recurse to possibly find the match. */
...@@ -2027,7 +2027,7 @@ maybe_fold_offset_to_component_ref (location_t loc, tree record_type, ...@@ -2027,7 +2027,7 @@ maybe_fold_offset_to_component_ref (location_t loc, tree record_type,
/* If we get here, we've got an aggregate field, and a possibly /* If we get here, we've got an aggregate field, and a possibly
nonzero offset into them. Recurse and hope for a valid match. */ nonzero offset into them. Recurse and hope for a valid match. */
base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE); base = fold_build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
SET_EXPR_LOCATION (base, loc); SET_EXPR_LOCATION (base, loc);
t = maybe_fold_offset_to_array_ref (loc, base, offset, orig_type, t = maybe_fold_offset_to_array_ref (loc, base, offset, orig_type,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment