alias.c (get_alias_set): Remove handling of PLACEHOLDER_EXPR.
* alias.c (get_alias_set): Remove handling of PLACEHOLDER_EXPR. * emit-rtl.c (component_ref_for_mem_expr): Likewise. (set_mem_attributes_minus_bitpos): Call SUBSTITUTE_PLACEHOLDER_IN_EXPR. * explow.c (expr_size): Likewise. * expr.h (placeholder_list, find_placeholder): Deleted. * expr.c (store_constructor): Likewise. (get_inner_reference): Likewise. Also don't call find_placeholder. (placeholder_list, find_placeholder): Deleted. (is_aligning_offset): Don't handle WITH_RECORD_EXPR, PLACEHOLDER_EXPR. (expand_expr_real, cases PLACEHOLDER_EXPR, WITH_RECORD_EXPR): Likewise. (highest_pow2_factor, case WITH_RECORD_EXPR): Remove. * dojump.c (do_jump, case WITH_RECORD_EXPR): Likewise. * dwarf2out.c (loc_descriptor_from_tree, case WITH_RECORD_EXPR): Likewise. * fold-const.c (invert_truthvalue, case WITH_RECORD_EXPR): Likewise. (extract_muldiv, case WITH_RECORD_EXPR): Likewise. * tree.c (expr_align, case WITH_RECORD_EXPR): Likewise. (contains_placeholder_p): Don't handle WITH_RECORD_EXPR. Clean up by using first_rtl_op. (substitute_in_expr): Use SUBSTITUTE_IN_EXPR for recursive call. (substitute_placeholder_in_expr): New function. * tree.def (WITH_RECORD_EXPR): Deleted. * tree.h (SUBSTITUTE_IN_EXPR, SUBSTITUTE_PLACEHOLDER_IN_EXPR): New. (substitute_placeholder_in_expr): New. * ada/decl.c (gnat_to_gnu_entity): Use SUBSTITUTE_PLACEHOLDER_IN_EXPR. * ada/trans.c (tree_transform, emit_index_check): Likewise. * ada/utils.c (build_template): Likewise. (max_size, convert): Remove handling of WITH_RECORD_EXPR. (maybe_unconstrained_array, unchecked_convert): Likewise. * ada/utils2.c (gnat_truthvalue_conversion, build_binary_op): Likewise. (build_unary_op): Likewise. (compare_arrays, build_allocator): Use SUBSTITUTE_PLACEHOLDER_IN_EXPR. (fill_vms_descriptor): Likewise. (build_call_alloc_dealloc): Likewise. ALIGN is unsigned. * ada/gigi.h (build_call_alloc_dealloc): Alignment is unsigned. From-SVN: r79789
This commit is contained in:
parent
fc5fccdee9
commit
6fce44af56
18 changed files with 260 additions and 391 deletions
|
@ -1,3 +1,30 @@
|
|||
2004-03-21 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* alias.c (get_alias_set): Remove handling of PLACEHOLDER_EXPR.
|
||||
* emit-rtl.c (component_ref_for_mem_expr): Likewise.
|
||||
(set_mem_attributes_minus_bitpos): Call SUBSTITUTE_PLACEHOLDER_IN_EXPR.
|
||||
* explow.c (expr_size): Likewise.
|
||||
* expr.h (placeholder_list, find_placeholder): Deleted.
|
||||
* expr.c (store_constructor): Likewise.
|
||||
(get_inner_reference): Likewise. Also don't call find_placeholder.
|
||||
(placeholder_list, find_placeholder): Deleted.
|
||||
(is_aligning_offset): Don't handle WITH_RECORD_EXPR, PLACEHOLDER_EXPR.
|
||||
(expand_expr_real, cases PLACEHOLDER_EXPR, WITH_RECORD_EXPR): Likewise.
|
||||
(highest_pow2_factor, case WITH_RECORD_EXPR): Remove.
|
||||
* dojump.c (do_jump, case WITH_RECORD_EXPR): Likewise.
|
||||
* dwarf2out.c (loc_descriptor_from_tree, case WITH_RECORD_EXPR):
|
||||
Likewise.
|
||||
* fold-const.c (invert_truthvalue, case WITH_RECORD_EXPR): Likewise.
|
||||
(extract_muldiv, case WITH_RECORD_EXPR): Likewise.
|
||||
* tree.c (expr_align, case WITH_RECORD_EXPR): Likewise.
|
||||
(contains_placeholder_p): Don't handle WITH_RECORD_EXPR.
|
||||
Clean up by using first_rtl_op.
|
||||
(substitute_in_expr): Use SUBSTITUTE_IN_EXPR for recursive call.
|
||||
(substitute_placeholder_in_expr): New function.
|
||||
* tree.def (WITH_RECORD_EXPR): Deleted.
|
||||
* tree.h (SUBSTITUTE_IN_EXPR, SUBSTITUTE_PLACEHOLDER_IN_EXPR): New.
|
||||
(substitute_placeholder_in_expr): New.
|
||||
|
||||
2004-03-21 Andrew Pinski <pinskia@gcc.gnu.org>
|
||||
|
||||
* dojump.c (prefer_and_bit_test): Fix which part of
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
2004-03-21 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* decl.c (gnat_to_gnu_entity): Use SUBSTITUTE_PLACEHOLDER_IN_EXPR.
|
||||
* trans.c (tree_transform, emit_index_check): Likewise.
|
||||
* utils.c (build_template): Likewise.
|
||||
(max_size, convert): Remove handling of WITH_RECORD_EXPR.
|
||||
(maybe_unconstrained_array, unchecked_convert): Likewise.
|
||||
* utils2.c (gnat_truthvalue_conversion, build_binary_op): Likewise.
|
||||
(build_unary_op): Likewise.
|
||||
(compare_arrays, build_allocator): Use SUBSTITUTE_PLACEHOLDER_IN_EXPR.
|
||||
(fill_vms_descriptor): Likewise.
|
||||
(build_call_alloc_dealloc): Likewise.
|
||||
ALIGN is unsigned.
|
||||
* gigi.h (build_call_alloc_dealloc): Alignment is unsigned.
|
||||
|
||||
2004-03-20 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
PR other/14630
|
||||
|
|
|
@ -565,12 +565,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|
|||
&& CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
|
||||
{
|
||||
if (gnu_expr != 0 && kind == E_Constant)
|
||||
{
|
||||
gnu_size = TYPE_SIZE (TREE_TYPE (gnu_expr));
|
||||
if (CONTAINS_PLACEHOLDER_P (gnu_size))
|
||||
gnu_size = build (WITH_RECORD_EXPR, bitsizetype,
|
||||
gnu_size, gnu_expr);
|
||||
}
|
||||
gnu_size
|
||||
= SUBSTITUTE_PLACEHOLDER_IN_EXPR
|
||||
(TYPE_SIZE (TREE_TYPE (gnu_expr)), gnu_expr);
|
||||
|
||||
/* We may have no GNU_EXPR because No_Initialization is
|
||||
set even though there's an Expression. */
|
||||
|
|
|
@ -701,7 +701,7 @@ extern tree build_component_ref (tree, tree, tree, int);
|
|||
GNU_SIZE is the size of the object and ALIGN is the alignment.
|
||||
GNAT_PROC, if present is a procedure to call and GNAT_POOL is the
|
||||
storage pool to use. If not preset, malloc and free will be used. */
|
||||
extern tree build_call_alloc_dealloc (tree, tree, int, Entity_Id,
|
||||
extern tree build_call_alloc_dealloc (tree, tree, unsigned int, Entity_Id,
|
||||
Entity_Id, Node_Id);
|
||||
|
||||
/* Build a GCC tree to correspond to allocating an object of TYPE whose
|
||||
|
|
|
@ -1236,8 +1236,8 @@ tree_transform (Node_Id gnat_node)
|
|||
if (CONTAINS_PLACEHOLDER_P (gnu_result))
|
||||
{
|
||||
if (TREE_CODE (gnu_prefix) != TYPE_DECL)
|
||||
gnu_result = build (WITH_RECORD_EXPR, TREE_TYPE (gnu_result),
|
||||
gnu_result, gnu_expr);
|
||||
gnu_result = substitute_placeholder_in_expr (gnu_result,
|
||||
gnu_expr);
|
||||
else
|
||||
gnu_result = max_size (gnu_result, 1);
|
||||
}
|
||||
|
@ -1381,9 +1381,8 @@ tree_transform (Node_Id gnat_node)
|
|||
/* If this has a PLACEHOLDER_EXPR, qualify it by the object
|
||||
we are handling. Note that these attributes could not
|
||||
have been used on an unconstrained array type. */
|
||||
if (CONTAINS_PLACEHOLDER_P (gnu_result))
|
||||
gnu_result = build (WITH_RECORD_EXPR, TREE_TYPE (gnu_result),
|
||||
gnu_result, gnu_prefix);
|
||||
gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result,
|
||||
gnu_prefix);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1486,9 +1485,8 @@ tree_transform (Node_Id gnat_node)
|
|||
|
||||
/* If this has a PLACEHOLDER_EXPR, qualify it by the object
|
||||
we are handling. */
|
||||
if (CONTAINS_PLACEHOLDER_P (gnu_result))
|
||||
gnu_result = build (WITH_RECORD_EXPR, TREE_TYPE (gnu_result),
|
||||
gnu_result, gnu_prefix);
|
||||
gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result,
|
||||
gnu_prefix);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1496,7 +1494,7 @@ tree_transform (Node_Id gnat_node)
|
|||
case Attr_Min:
|
||||
case Attr_Max:
|
||||
gnu_lhs = gnat_to_gnu (First (Expressions (gnat_node)));
|
||||
gnu_rhs = gnat_to_gnu (Next (First (Expressions (gnat_node))));
|
||||
gnu_rhs = gnat_to_gnu (Next (First (Expressions (gnat_node))));
|
||||
|
||||
gnu_result_type = get_unpadded_type (Etype (gnat_node));
|
||||
gnu_result = build_binary_op (attribute == Attr_Min
|
||||
|
@ -4622,13 +4620,8 @@ emit_index_check (tree gnu_array_object,
|
|||
|
||||
/* If GNU_LOW or GNU_HIGH are a PLACEHOLDER_EXPR, qualify them by
|
||||
the object we are handling. */
|
||||
if (CONTAINS_PLACEHOLDER_P (gnu_low))
|
||||
gnu_low = build (WITH_RECORD_EXPR, TREE_TYPE (gnu_low),
|
||||
gnu_low, gnu_array_object);
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (gnu_high))
|
||||
gnu_high = build (WITH_RECORD_EXPR, TREE_TYPE (gnu_high),
|
||||
gnu_high, gnu_array_object);
|
||||
gnu_low = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_low, gnu_array_object);
|
||||
gnu_high = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_high, gnu_array_object);
|
||||
|
||||
/* There's no good type to use here, so we might as well use
|
||||
integer_type_node. */
|
||||
|
|
|
@ -2180,8 +2180,6 @@ max_size (tree exp, int max_p)
|
|||
gigi_abort (407);
|
||||
else if (code == COMPOUND_EXPR)
|
||||
return max_size (TREE_OPERAND (exp, 1), max_p);
|
||||
else if (code == WITH_RECORD_EXPR)
|
||||
return exp;
|
||||
|
||||
{
|
||||
tree lhs = max_size (TREE_OPERAND (exp, 0), max_p);
|
||||
|
@ -2275,12 +2273,9 @@ build_template (tree template_type, tree array_type, tree expr)
|
|||
max = convert (TREE_TYPE (field), TYPE_MAX_VALUE (bounds));
|
||||
|
||||
/* If either MIN or MAX involve a PLACEHOLDER_EXPR, we must
|
||||
surround them with a WITH_RECORD_EXPR giving EXPR as the
|
||||
OBJECT. */
|
||||
if (CONTAINS_PLACEHOLDER_P (min))
|
||||
min = build (WITH_RECORD_EXPR, TREE_TYPE (min), min, expr);
|
||||
if (CONTAINS_PLACEHOLDER_P (max))
|
||||
max = build (WITH_RECORD_EXPR, TREE_TYPE (max), max, expr);
|
||||
substitute it from OBJECT. */
|
||||
min = SUBSTITUTE_PLACEHOLDER_IN_EXPR (min, expr);
|
||||
max = SUBSTITUTE_PLACEHOLDER_IN_EXPR (max, expr);
|
||||
|
||||
template_elts = tree_cons (TREE_CHAIN (field), max,
|
||||
tree_cons (field, min, template_elts));
|
||||
|
@ -2865,12 +2860,6 @@ convert (tree type, tree expr)
|
|||
else if (AGGREGATE_TYPE_P (type)
|
||||
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype))
|
||||
return build1 (NOP_EXPR, type, expr);
|
||||
/* If EXPR is a WITH_RECORD_EXPR, do the conversion inside and then make a
|
||||
new one. */
|
||||
else if (TREE_CODE (expr) == WITH_RECORD_EXPR)
|
||||
return build (WITH_RECORD_EXPR, type,
|
||||
convert (type, TREE_OPERAND (expr, 0)),
|
||||
TREE_OPERAND (expr, 1));
|
||||
|
||||
/* If the input type has padding, remove it by doing a component reference
|
||||
to the field. If the output type has padding, make a constructor
|
||||
|
@ -3250,13 +3239,6 @@ maybe_unconstrained_array (tree exp)
|
|||
(TREE_TYPE (TREE_TYPE (exp))))),
|
||||
TREE_OPERAND (exp, 0));
|
||||
|
||||
else if (code == WITH_RECORD_EXPR
|
||||
&& (TREE_OPERAND (exp, 0)
|
||||
!= (new = maybe_unconstrained_array
|
||||
(TREE_OPERAND (exp, 0)))))
|
||||
return build (WITH_RECORD_EXPR, TREE_TYPE (new), new,
|
||||
TREE_OPERAND (exp, 1));
|
||||
|
||||
case RECORD_TYPE:
|
||||
/* If this is a padded type, convert to the unpadded type and see if
|
||||
it contains a template. */
|
||||
|
@ -3295,13 +3277,6 @@ unchecked_convert (tree type, tree expr, int notrunc_p)
|
|||
if (etype == type)
|
||||
return expr;
|
||||
|
||||
/* If EXPR is a WITH_RECORD_EXPR, do the conversion inside and then make a
|
||||
new one. */
|
||||
if (TREE_CODE (expr) == WITH_RECORD_EXPR)
|
||||
return build (WITH_RECORD_EXPR, type,
|
||||
unchecked_convert (type, TREE_OPERAND (expr, 0), notrunc_p),
|
||||
TREE_OPERAND (expr, 1));
|
||||
|
||||
/* If both types types are integral just do a normal conversion.
|
||||
Likewise for a conversion to an unconstrained array. */
|
||||
if ((((INTEGRAL_TYPE_P (type)
|
||||
|
|
105
gcc/ada/utils2.c
105
gcc/ada/utils2.c
|
@ -90,11 +90,6 @@ gnat_truthvalue_conversion (tree expr)
|
|||
gnat_truthvalue_conversion (TREE_OPERAND (expr, 1)),
|
||||
gnat_truthvalue_conversion (TREE_OPERAND (expr, 2))));
|
||||
|
||||
case WITH_RECORD_EXPR:
|
||||
return build (WITH_RECORD_EXPR, type,
|
||||
gnat_truthvalue_conversion (TREE_OPERAND (expr, 0)),
|
||||
TREE_OPERAND (expr, 1));
|
||||
|
||||
default:
|
||||
return build_binary_op (NE_EXPR, type, expr,
|
||||
convert (type, integer_zero_node));
|
||||
|
@ -381,15 +376,10 @@ compare_arrays (tree result_type, tree a1, tree a2)
|
|||
tree lb = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
|
||||
|
||||
comparison = build_binary_op (LT_EXPR, result_type, ub, lb);
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (comparison))
|
||||
comparison = build (WITH_RECORD_EXPR, result_type,
|
||||
comparison, a1);
|
||||
if (CONTAINS_PLACEHOLDER_P (length1))
|
||||
length1 = build (WITH_RECORD_EXPR, bt, length1, a1);
|
||||
comparison = SUBSTITUTE_PLACEHOLDER_IN_EXPR (comparison, a1);
|
||||
length1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length1, a1);
|
||||
|
||||
length_zero_p = 1;
|
||||
|
||||
this_a1_is_null = comparison;
|
||||
this_a2_is_null = convert (result_type, integer_one_node);
|
||||
}
|
||||
|
@ -413,10 +403,8 @@ compare_arrays (tree result_type, tree a1, tree a2)
|
|||
/* Note that we know that UB2 and LB2 are constant and hence
|
||||
cannot contain a PLACEHOLDER_EXPR. */
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (comparison))
|
||||
comparison = build (WITH_RECORD_EXPR, result_type, comparison, a1);
|
||||
if (CONTAINS_PLACEHOLDER_P (length1))
|
||||
length1 = build (WITH_RECORD_EXPR, bt, length1, a1);
|
||||
comparison = SUBSTITUTE_PLACEHOLDER_IN_EXPR (comparison, a1);
|
||||
length1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length1, a1);
|
||||
|
||||
this_a1_is_null = build_binary_op (LT_EXPR, result_type, ub1, lb1);
|
||||
this_a2_is_null = convert (result_type, integer_zero_node);
|
||||
|
@ -425,10 +413,8 @@ compare_arrays (tree result_type, tree a1, tree a2)
|
|||
/* Otherwise compare the computed lengths. */
|
||||
else
|
||||
{
|
||||
if (CONTAINS_PLACEHOLDER_P (length1))
|
||||
length1 = build (WITH_RECORD_EXPR, bt, length1, a1);
|
||||
if (CONTAINS_PLACEHOLDER_P (length2))
|
||||
length2 = build (WITH_RECORD_EXPR, bt, length2, a2);
|
||||
length1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length1, a1);
|
||||
length2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (length2, a2);
|
||||
|
||||
comparison
|
||||
= build_binary_op (EQ_EXPR, result_type, length1, length2);
|
||||
|
@ -606,39 +592,6 @@ build_binary_op (enum tree_code op_code,
|
|||
tree result;
|
||||
int has_side_effects = 0;
|
||||
|
||||
/* If one (but not both, unless they have the same object) operands are a
|
||||
WITH_RECORD_EXPR, do the operation and then surround it with the
|
||||
WITH_RECORD_EXPR. Don't do this for assignment, for an ARRAY_REF, or
|
||||
for an ARRAY_RANGE_REF because we need to keep track of the
|
||||
WITH_RECORD_EXPRs on both operands very carefully. */
|
||||
if (op_code != MODIFY_EXPR && op_code != ARRAY_REF
|
||||
&& op_code != ARRAY_RANGE_REF
|
||||
&& TREE_CODE (left_operand) == WITH_RECORD_EXPR
|
||||
&& (TREE_CODE (right_operand) != WITH_RECORD_EXPR
|
||||
|| operand_equal_p (TREE_OPERAND (left_operand, 1),
|
||||
TREE_OPERAND (right_operand, 1), 0)))
|
||||
{
|
||||
tree right = right_operand;
|
||||
|
||||
if (TREE_CODE (right) == WITH_RECORD_EXPR)
|
||||
right = TREE_OPERAND (right, 0);
|
||||
|
||||
result = build_binary_op (op_code, result_type,
|
||||
TREE_OPERAND (left_operand, 0), right);
|
||||
return build (WITH_RECORD_EXPR, TREE_TYPE (result), result,
|
||||
TREE_OPERAND (left_operand, 1));
|
||||
}
|
||||
else if (op_code != MODIFY_EXPR && op_code != ARRAY_REF
|
||||
&& op_code != ARRAY_RANGE_REF
|
||||
&& TREE_CODE (left_operand) != WITH_RECORD_EXPR
|
||||
&& TREE_CODE (right_operand) == WITH_RECORD_EXPR)
|
||||
{
|
||||
result = build_binary_op (op_code, result_type, left_operand,
|
||||
TREE_OPERAND (right_operand, 0));
|
||||
return build (WITH_RECORD_EXPR, TREE_TYPE (result), result,
|
||||
TREE_OPERAND (right_operand, 1));
|
||||
}
|
||||
|
||||
if (operation_type != 0
|
||||
&& TREE_CODE (operation_type) == RECORD_TYPE
|
||||
&& TYPE_LEFT_JUSTIFIED_MODULAR_P (operation_type))
|
||||
|
@ -755,7 +708,6 @@ build_binary_op (enum tree_code op_code,
|
|||
result = TREE_OPERAND (result, 0);
|
||||
else if (TREE_CODE (result) == REALPART_EXPR
|
||||
|| TREE_CODE (result) == IMAGPART_EXPR
|
||||
|| TREE_CODE (result) == WITH_RECORD_EXPR
|
||||
|| ((TREE_CODE (result) == NOP_EXPR
|
||||
|| TREE_CODE (result) == CONVERT_EXPR)
|
||||
&& (((TREE_CODE (restype)
|
||||
|
@ -1091,17 +1043,6 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
|
|||
tree result;
|
||||
int side_effects = 0;
|
||||
|
||||
/* If we have a WITH_RECORD_EXPR as our operand, do the operation first,
|
||||
then surround it with the WITH_RECORD_EXPR. This allows GCC to do better
|
||||
expression folding. */
|
||||
if (TREE_CODE (operand) == WITH_RECORD_EXPR)
|
||||
{
|
||||
result = build_unary_op (op_code, result_type,
|
||||
TREE_OPERAND (operand, 0));
|
||||
return build (WITH_RECORD_EXPR, TREE_TYPE (result), result,
|
||||
TREE_OPERAND (operand, 1));
|
||||
}
|
||||
|
||||
if (operation_type != 0
|
||||
&& TREE_CODE (operation_type) == RECORD_TYPE
|
||||
&& TYPE_LEFT_JUSTIFIED_MODULAR_P (operation_type))
|
||||
|
@ -1716,18 +1657,13 @@ build_component_ref (tree record_variable,
|
|||
object dynamically on the stack frame. */
|
||||
|
||||
tree
|
||||
build_call_alloc_dealloc (tree gnu_obj,
|
||||
tree gnu_size,
|
||||
int align,
|
||||
Entity_Id gnat_proc,
|
||||
Entity_Id gnat_pool,
|
||||
build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, unsigned align,
|
||||
Entity_Id gnat_proc, Entity_Id gnat_pool,
|
||||
Node_Id gnat_node)
|
||||
{
|
||||
tree gnu_align = size_int (align / BITS_PER_UNIT);
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (gnu_size))
|
||||
gnu_size = build (WITH_RECORD_EXPR, sizetype, gnu_size,
|
||||
build_unary_op (INDIRECT_REF, NULL_TREE, gnu_obj));
|
||||
gnu_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_size, gnu_obj);
|
||||
|
||||
if (Present (gnat_proc))
|
||||
{
|
||||
|
@ -1868,10 +1804,8 @@ build_allocator (tree type,
|
|||
tree storage;
|
||||
tree template_cons = NULL_TREE;
|
||||
|
||||
size = TYPE_SIZE_UNIT (storage_type);
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (size))
|
||||
size = build (WITH_RECORD_EXPR, sizetype, size, init);
|
||||
size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (storage_type),
|
||||
init);
|
||||
|
||||
/* If the size overflows, pass -1 so the allocator will raise
|
||||
storage error. */
|
||||
|
@ -1943,7 +1877,7 @@ build_allocator (tree type,
|
|||
if (init == 0)
|
||||
size = max_size (size, 1);
|
||||
else
|
||||
size = build (WITH_RECORD_EXPR, sizetype, size, init);
|
||||
size = substitute_placeholder_in_expr (size, init);
|
||||
}
|
||||
|
||||
/* If the size overflows, pass -1 so the allocator will raise
|
||||
|
@ -2012,15 +1946,12 @@ fill_vms_descriptor (tree expr, Entity_Id gnat_formal)
|
|||
gnat_mark_addressable (expr);
|
||||
|
||||
for (field = TYPE_FIELDS (record_type); field; field = TREE_CHAIN (field))
|
||||
{
|
||||
tree init = DECL_INITIAL (field);
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (init))
|
||||
init = build (WITH_RECORD_EXPR, TREE_TYPE (init), init, expr);
|
||||
|
||||
const_list = tree_cons (field, convert (TREE_TYPE (field), init),
|
||||
const_list);
|
||||
}
|
||||
const_list
|
||||
= tree_cons (field,
|
||||
convert (TREE_TYPE (field),
|
||||
SUBSTITUTE_PLACEHOLDER_IN_EXPR
|
||||
(DECL_INITIAL (field), expr)),
|
||||
const_list);
|
||||
|
||||
return gnat_build_constructor (record_type, nreverse (const_list));
|
||||
}
|
||||
|
|
25
gcc/alias.c
25
gcc/alias.c
|
@ -481,7 +481,6 @@ get_alias_set (tree t)
|
|||
if (! TYPE_P (t))
|
||||
{
|
||||
tree inner = t;
|
||||
tree placeholder_ptr = 0;
|
||||
|
||||
/* Remove any nops, then give the language a chance to do
|
||||
something with this tree before we look at it. */
|
||||
|
@ -491,16 +490,10 @@ get_alias_set (tree t)
|
|||
return set;
|
||||
|
||||
/* First see if the actual object referenced is an INDIRECT_REF from a
|
||||
restrict-qualified pointer or a "void *". Replace
|
||||
PLACEHOLDER_EXPRs. */
|
||||
while (TREE_CODE (inner) == PLACEHOLDER_EXPR
|
||||
|| handled_component_p (inner))
|
||||
restrict-qualified pointer or a "void *". */
|
||||
while (handled_component_p (inner))
|
||||
{
|
||||
if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
|
||||
inner = find_placeholder (inner, &placeholder_ptr);
|
||||
else
|
||||
inner = TREE_OPERAND (inner, 0);
|
||||
|
||||
inner = TREE_OPERAND (inner, 0);
|
||||
STRIP_NOPS (inner);
|
||||
}
|
||||
|
||||
|
@ -546,16 +539,10 @@ get_alias_set (tree t)
|
|||
}
|
||||
|
||||
/* Otherwise, pick up the outermost object that we could have a pointer
|
||||
to, processing conversion and PLACEHOLDER_EXPR as above. */
|
||||
placeholder_ptr = 0;
|
||||
while (TREE_CODE (t) == PLACEHOLDER_EXPR
|
||||
|| (handled_component_p (t) && ! can_address_p (t)))
|
||||
to, processing conversions as above. */
|
||||
while (handled_component_p (t) && ! can_address_p (t))
|
||||
{
|
||||
if (TREE_CODE (t) == PLACEHOLDER_EXPR)
|
||||
t = find_placeholder (t, &placeholder_ptr);
|
||||
else
|
||||
t = TREE_OPERAND (t, 0);
|
||||
|
||||
t = TREE_OPERAND (t, 0);
|
||||
STRIP_NOPS (t);
|
||||
}
|
||||
|
||||
|
|
|
@ -217,15 +217,6 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
|
|||
do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
|
||||
break;
|
||||
|
||||
case WITH_RECORD_EXPR:
|
||||
/* Put the object on the placeholder list, recurse through our first
|
||||
operand, and pop the list. */
|
||||
placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
|
||||
placeholder_list);
|
||||
do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
|
||||
placeholder_list = TREE_CHAIN (placeholder_list);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
/* This is never less insns than evaluating the PLUS_EXPR followed by
|
||||
a test and can be longer if the test is eliminated. */
|
||||
|
|
|
@ -8705,7 +8705,6 @@ loc_descriptor_from_tree (tree loc, int addressp)
|
|||
case ERROR_MARK:
|
||||
return 0;
|
||||
|
||||
case WITH_RECORD_EXPR:
|
||||
case PLACEHOLDER_EXPR:
|
||||
/* This case involves extracting fields from an object to determine the
|
||||
position of other fields. We don't try to encode this here. The
|
||||
|
|
|
@ -1409,19 +1409,13 @@ component_ref_for_mem_expr (tree ref)
|
|||
inner = component_ref_for_mem_expr (inner);
|
||||
else
|
||||
{
|
||||
tree placeholder_ptr = 0;
|
||||
|
||||
/* Now remove any conversions: they don't change what the underlying
|
||||
object is. Likewise for SAVE_EXPR. Also handle PLACEHOLDER_EXPR. */
|
||||
object is. Likewise for SAVE_EXPR. */
|
||||
while (TREE_CODE (inner) == NOP_EXPR || TREE_CODE (inner) == CONVERT_EXPR
|
||||
|| TREE_CODE (inner) == NON_LVALUE_EXPR
|
||||
|| TREE_CODE (inner) == VIEW_CONVERT_EXPR
|
||||
|| TREE_CODE (inner) == SAVE_EXPR
|
||||
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
|
||||
if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
|
||||
inner = find_placeholder (inner, &placeholder_ptr);
|
||||
else
|
||||
inner = TREE_OPERAND (inner, 0);
|
||||
|| TREE_CODE (inner) == SAVE_EXPR)
|
||||
inner = TREE_OPERAND (inner, 0);
|
||||
|
||||
if (! DECL_P (inner))
|
||||
inner = NULL_TREE;
|
||||
|
@ -1608,20 +1602,14 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
|
|||
index = fold (build (MINUS_EXPR, TREE_TYPE (index),
|
||||
index, low_bound));
|
||||
|
||||
/* If the index has a self-referential type, pass it to a
|
||||
WITH_RECORD_EXPR; if the component size is, pass our
|
||||
component to one. */
|
||||
if (CONTAINS_PLACEHOLDER_P (index))
|
||||
index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t2);
|
||||
if (CONTAINS_PLACEHOLDER_P (unit_size))
|
||||
unit_size = build (WITH_RECORD_EXPR, sizetype,
|
||||
unit_size, array);
|
||||
|
||||
/* If the index has a self-referential type, instantiate it;
|
||||
likewise for the component size. */
|
||||
index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, t2);
|
||||
unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array);
|
||||
off_tree
|
||||
= fold (build (PLUS_EXPR, sizetype,
|
||||
fold (build (MULT_EXPR, sizetype,
|
||||
index,
|
||||
unit_size)),
|
||||
index, unit_size)),
|
||||
off_tree));
|
||||
t2 = TREE_OPERAND (t2, 0);
|
||||
}
|
||||
|
|
|
@ -240,10 +240,7 @@ eliminate_constant_term (rtx x, rtx *constptr)
|
|||
rtx
|
||||
expr_size (tree exp)
|
||||
{
|
||||
tree size = lang_hooks.expr_size (exp);
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (size))
|
||||
size = build (WITH_RECORD_EXPR, sizetype, size, exp);
|
||||
tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
|
||||
|
||||
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
|
||||
}
|
||||
|
|
147
gcc/expr.c
147
gcc/expr.c
|
@ -90,9 +90,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
the same indirect address eventually. */
|
||||
int cse_not_expected;
|
||||
|
||||
/* Chain of pending expressions for PLACEHOLDER_EXPR to replace. */
|
||||
tree placeholder_list = 0;
|
||||
|
||||
/* This structure is used by move_by_pieces to describe the move to
|
||||
be performed. */
|
||||
struct move_by_pieces
|
||||
|
@ -4610,9 +4607,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
{
|
||||
rtx offset_rtx;
|
||||
|
||||
if (CONTAINS_PLACEHOLDER_P (offset))
|
||||
offset = build (WITH_RECORD_EXPR, sizetype,
|
||||
offset, make_tree (TREE_TYPE (exp), target));
|
||||
offset
|
||||
= SUBSTITUTE_PLACEHOLDER_IN_EXPR (offset,
|
||||
make_tree (TREE_TYPE (exp),
|
||||
target));
|
||||
|
||||
offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
|
||||
if (GET_CODE (to_rtx) != MEM)
|
||||
|
@ -5401,7 +5399,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
|
|||
enum machine_mode mode = VOIDmode;
|
||||
tree offset = size_zero_node;
|
||||
tree bit_offset = bitsize_zero_node;
|
||||
tree placeholder_ptr = 0;
|
||||
tree tem;
|
||||
|
||||
/* First get the mode, signedness, and size. We do this from just the
|
||||
|
@ -5454,8 +5451,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
|
|||
made during type construction. */
|
||||
if (this_offset == 0)
|
||||
break;
|
||||
else if (CONTAINS_PLACEHOLDER_P (this_offset))
|
||||
this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
|
||||
else
|
||||
this_offset = SUBSTITUTE_PLACEHOLDER_IN_EXPR (this_offset, exp);
|
||||
|
||||
offset = size_binop (PLUS_EXPR, offset, this_offset);
|
||||
bit_offset = size_binop (PLUS_EXPR, bit_offset,
|
||||
|
@ -5481,35 +5478,16 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
|
|||
index = fold (build (MINUS_EXPR, TREE_TYPE (index),
|
||||
index, low_bound));
|
||||
|
||||
/* If the index has a self-referential type, pass it to a
|
||||
WITH_RECORD_EXPR; if the component size is, pass our
|
||||
component to one. */
|
||||
if (CONTAINS_PLACEHOLDER_P (index))
|
||||
index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
|
||||
if (CONTAINS_PLACEHOLDER_P (unit_size))
|
||||
unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array);
|
||||
|
||||
/* If the index has a self-referential type, instantiate it with
|
||||
the object; likewise fkor the component size. */
|
||||
index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, exp);
|
||||
unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array);
|
||||
offset = size_binop (PLUS_EXPR, offset,
|
||||
size_binop (MULT_EXPR,
|
||||
convert (sizetype, index),
|
||||
unit_size));
|
||||
}
|
||||
|
||||
else if (TREE_CODE (exp) == PLACEHOLDER_EXPR)
|
||||
{
|
||||
tree new = find_placeholder (exp, &placeholder_ptr);
|
||||
|
||||
/* If we couldn't find the replacement, return the PLACEHOLDER_EXPR.
|
||||
We might have been called from tree optimization where we
|
||||
haven't set up an object yet. */
|
||||
if (new == 0)
|
||||
break;
|
||||
else
|
||||
exp = new;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We can go inside most conversions: all NON_VALUE_EXPRs, all normal
|
||||
conversions that don't change the mode, and all view conversions
|
||||
except those that need to "step up" the alignment. */
|
||||
|
@ -6033,7 +6011,7 @@ highest_pow2_factor (tree exp)
|
|||
break;
|
||||
|
||||
case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR:
|
||||
case SAVE_EXPR: case WITH_RECORD_EXPR:
|
||||
case SAVE_EXPR:
|
||||
return highest_pow2_factor (TREE_OPERAND (exp, 0));
|
||||
|
||||
case COMPOUND_EXPR:
|
||||
|
@ -6069,70 +6047,6 @@ highest_pow2_factor_for_target (tree target, tree exp)
|
|||
return MAX (factor, target_align);
|
||||
}
|
||||
|
||||
/* Return an object on the placeholder list that matches EXP, a
|
||||
PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
|
||||
PLACEHOLDER_EXPR or a pointer type to it. For further information, see
|
||||
tree.def. If no such object is found, return 0. If PLIST is nonzero, it
|
||||
is a location which initially points to a starting location in the
|
||||
placeholder list (zero means start of the list) and where a pointer into
|
||||
the placeholder list at which the object is found is placed. */
|
||||
|
||||
tree
|
||||
find_placeholder (tree exp, tree *plist)
|
||||
{
|
||||
tree type = TREE_TYPE (exp);
|
||||
tree placeholder_expr;
|
||||
|
||||
for (placeholder_expr
|
||||
= plist && *plist ? TREE_CHAIN (*plist) : placeholder_list;
|
||||
placeholder_expr != 0;
|
||||
placeholder_expr = TREE_CHAIN (placeholder_expr))
|
||||
{
|
||||
tree need_type = TYPE_MAIN_VARIANT (type);
|
||||
tree elt;
|
||||
|
||||
/* Find the outermost reference that is of the type we want. If none,
|
||||
see if any object has a type that is a pointer to the type we
|
||||
want. */
|
||||
for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
|
||||
elt = ((TREE_CODE (elt) == COMPOUND_EXPR
|
||||
|| TREE_CODE (elt) == COND_EXPR)
|
||||
? TREE_OPERAND (elt, 1)
|
||||
: (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
|
||||
? TREE_OPERAND (elt, 0) : 0))
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
|
||||
{
|
||||
if (plist)
|
||||
*plist = placeholder_expr;
|
||||
return elt;
|
||||
}
|
||||
|
||||
for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
|
||||
elt
|
||||
= ((TREE_CODE (elt) == COMPOUND_EXPR
|
||||
|| TREE_CODE (elt) == COND_EXPR)
|
||||
? TREE_OPERAND (elt, 1)
|
||||
: (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
|
||||
? TREE_OPERAND (elt, 0) : 0))
|
||||
if (POINTER_TYPE_P (TREE_TYPE (elt))
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
|
||||
== need_type))
|
||||
{
|
||||
if (plist)
|
||||
*plist = placeholder_expr;
|
||||
return build1 (INDIRECT_REF, need_type, elt);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Subroutine of expand_expr. Expand the two operands of a binary
|
||||
expression EXP0 and EXP1 placing the results in OP0 and OP1.
|
||||
The value may be stored in TARGET if TARGET is nonzero. The
|
||||
|
@ -6653,31 +6567,6 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
|
|||
return temp;
|
||||
}
|
||||
|
||||
case PLACEHOLDER_EXPR:
|
||||
{
|
||||
tree old_list = placeholder_list;
|
||||
tree placeholder_expr = 0;
|
||||
|
||||
exp = find_placeholder (exp, &placeholder_expr);
|
||||
if (exp == 0)
|
||||
abort ();
|
||||
|
||||
placeholder_list = TREE_CHAIN (placeholder_expr);
|
||||
temp = expand_expr (exp, original_target, tmode, modifier);
|
||||
placeholder_list = old_list;
|
||||
return temp;
|
||||
}
|
||||
|
||||
case WITH_RECORD_EXPR:
|
||||
/* Put the object on the placeholder list, expand our first operand,
|
||||
and pop the list. */
|
||||
placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
|
||||
placeholder_list);
|
||||
target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode,
|
||||
modifier);
|
||||
placeholder_list = TREE_CHAIN (placeholder_list);
|
||||
return target;
|
||||
|
||||
case GOTO_EXPR:
|
||||
if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
|
||||
expand_goto (TREE_OPERAND (exp, 0));
|
||||
|
@ -9095,11 +8984,10 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
|
|||
static int
|
||||
is_aligning_offset (tree offset, tree exp)
|
||||
{
|
||||
/* Strip off any conversions and WITH_RECORD_EXPR nodes. */
|
||||
/* Strip off any conversions. */
|
||||
while (TREE_CODE (offset) == NON_LVALUE_EXPR
|
||||
|| TREE_CODE (offset) == NOP_EXPR
|
||||
|| TREE_CODE (offset) == CONVERT_EXPR
|
||||
|| TREE_CODE (offset) == WITH_RECORD_EXPR)
|
||||
|| TREE_CODE (offset) == CONVERT_EXPR)
|
||||
offset = TREE_OPERAND (offset, 0);
|
||||
|
||||
/* We must now have a BIT_AND_EXPR with a constant that is one less than
|
||||
|
@ -9128,13 +9016,8 @@ is_aligning_offset (tree offset, tree exp)
|
|||
|| TREE_CODE (offset) == CONVERT_EXPR)
|
||||
offset = TREE_OPERAND (offset, 0);
|
||||
|
||||
/* This must now be the address either of EXP or of a PLACEHOLDER_EXPR
|
||||
whose type is the same as EXP. */
|
||||
return (TREE_CODE (offset) == ADDR_EXPR
|
||||
&& (TREE_OPERAND (offset, 0) == exp
|
||||
|| (TREE_CODE (TREE_OPERAND (offset, 0)) == PLACEHOLDER_EXPR
|
||||
&& (TREE_TYPE (TREE_OPERAND (offset, 0))
|
||||
== TREE_TYPE (exp)))));
|
||||
/* This must now be the address of EXP. */
|
||||
return TREE_CODE (offset) == ADDR_EXPR && TREE_OPERAND (offset, 0) == exp;
|
||||
}
|
||||
|
||||
/* Return the tree node if an ARG corresponds to a string constant or zero
|
||||
|
|
11
gcc/expr.h
11
gcc/expr.h
|
@ -505,15 +505,6 @@ extern rtx store_expr (tree, rtx, int);
|
|||
Useful after calling expand_expr with 1 as sum_ok. */
|
||||
extern rtx force_operand (rtx, rtx);
|
||||
|
||||
/* Return an object on the placeholder list that matches EXP, a
|
||||
PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
|
||||
PLACEHOLDER_EXPR or a pointer type to it. For further information, see
|
||||
tree.def. If no such object is found, abort. If PLIST is nonzero, it is
|
||||
a location which initially points to a starting location in the
|
||||
placeholder list (zero means start of the list) and where a pointer into
|
||||
the placeholder list at which the object is found is placed. */
|
||||
extern tree find_placeholder (tree, tree *);
|
||||
|
||||
/* Generate code for computing expression EXP.
|
||||
An rtx for the computed value is returned. The value is never null.
|
||||
In the case of a void EXP, const0_rtx is returned. */
|
||||
|
@ -808,5 +799,3 @@ extern void do_jump_by_parts_greater_rtx (enum machine_mode, int, rtx, rtx,
|
|||
extern void mark_seen_cases (tree, unsigned char *, HOST_WIDE_INT, int);
|
||||
|
||||
extern int vector_mode_valid_p (enum machine_mode);
|
||||
|
||||
extern tree placeholder_list;
|
||||
|
|
|
@ -2718,11 +2718,6 @@ invert_truthvalue (tree arg)
|
|||
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
|
||||
invert_truthvalue (TREE_OPERAND (arg, 1)));
|
||||
|
||||
case WITH_RECORD_EXPR:
|
||||
return build (WITH_RECORD_EXPR, type,
|
||||
invert_truthvalue (TREE_OPERAND (arg, 0)),
|
||||
TREE_OPERAND (arg, 1));
|
||||
|
||||
case NON_LVALUE_EXPR:
|
||||
return invert_truthvalue (TREE_OPERAND (arg, 0));
|
||||
|
||||
|
@ -4560,12 +4555,6 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
|
|||
}
|
||||
break;
|
||||
|
||||
case WITH_RECORD_EXPR:
|
||||
if ((t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code, wide_type)) != 0)
|
||||
return build (WITH_RECORD_EXPR, TREE_TYPE (t1), t1,
|
||||
TREE_OPERAND (t, 1));
|
||||
break;
|
||||
|
||||
case LSHIFT_EXPR: case RSHIFT_EXPR:
|
||||
/* If the second operand is constant, this is a multiplication
|
||||
or floor division, by a power of two, so we can treat it that
|
||||
|
|
151
gcc/tree.c
151
gcc/tree.c
|
@ -1211,7 +1211,7 @@ expr_align (tree t)
|
|||
|
||||
case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR:
|
||||
case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR:
|
||||
case WITH_RECORD_EXPR: case CLEANUP_POINT_EXPR: case UNSAVE_EXPR:
|
||||
case CLEANUP_POINT_EXPR: case UNSAVE_EXPR:
|
||||
/* These don't change the alignment of an object. */
|
||||
return expr_align (TREE_OPERAND (t, 0));
|
||||
|
||||
|
@ -1699,12 +1699,8 @@ contains_placeholder_p (tree exp)
|
|||
if (!exp)
|
||||
return 0;
|
||||
|
||||
/* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR
|
||||
in it since it is supplying a value for it. */
|
||||
code = TREE_CODE (exp);
|
||||
if (code == WITH_RECORD_EXPR)
|
||||
return 0;
|
||||
else if (code == PLACEHOLDER_EXPR)
|
||||
if (code == PLACEHOLDER_EXPR)
|
||||
return 1;
|
||||
|
||||
switch (TREE_CODE_CLASS (code))
|
||||
|
@ -1731,10 +1727,6 @@ contains_placeholder_p (tree exp)
|
|||
/* Ignoring the first operand isn't quite right, but works best. */
|
||||
return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
|
||||
|
||||
case RTL_EXPR:
|
||||
case CONSTRUCTOR:
|
||||
return 0;
|
||||
|
||||
case COND_EXPR:
|
||||
return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
|
||||
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
|
||||
|
@ -1753,14 +1745,11 @@ contains_placeholder_p (tree exp)
|
|||
|
||||
return result;
|
||||
|
||||
case CALL_EXPR:
|
||||
return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (TREE_CODE_LENGTH (code))
|
||||
switch (first_rtl_op (code))
|
||||
{
|
||||
case 1:
|
||||
return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
|
||||
|
@ -1954,9 +1943,8 @@ substitute_in_expr (tree exp, tree f, tree r)
|
|||
/* We handle TREE_LIST and COMPONENT_REF separately. */
|
||||
if (code == TREE_LIST)
|
||||
{
|
||||
op0 = (TREE_CHAIN (exp) == 0
|
||||
? 0 : substitute_in_expr (TREE_CHAIN (exp), f, r));
|
||||
op1 = substitute_in_expr (TREE_VALUE (exp), f, r);
|
||||
op0 = SUBSTITUTE_IN_EXPR (TREE_CHAIN (exp), f, r);
|
||||
op1 = SUBSTITUTE_IN_EXPR (TREE_VALUE (exp), f, r);
|
||||
if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
|
||||
return exp;
|
||||
|
||||
|
@ -1979,7 +1967,7 @@ substitute_in_expr (tree exp, tree f, tree r)
|
|||
if (TREE_CODE (inner) == PLACEHOLDER_EXPR && TREE_TYPE (inner) == 0)
|
||||
return exp;
|
||||
|
||||
op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
|
||||
op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
|
||||
if (op0 == TREE_OPERAND (exp, 0))
|
||||
return exp;
|
||||
|
||||
|
@ -2004,7 +1992,7 @@ substitute_in_expr (tree exp, tree f, tree r)
|
|||
return exp;
|
||||
|
||||
case 1:
|
||||
op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
|
||||
op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
|
||||
if (op0 == TREE_OPERAND (exp, 0))
|
||||
return exp;
|
||||
|
||||
|
@ -2012,8 +2000,8 @@ substitute_in_expr (tree exp, tree f, tree r)
|
|||
break;
|
||||
|
||||
case 2:
|
||||
op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
|
||||
op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
|
||||
op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
|
||||
op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
|
||||
|
||||
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
|
||||
return exp;
|
||||
|
@ -2022,9 +2010,9 @@ substitute_in_expr (tree exp, tree f, tree r)
|
|||
break;
|
||||
|
||||
case 3:
|
||||
op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
|
||||
op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
|
||||
op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
|
||||
op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
|
||||
op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
|
||||
op2 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 2), f, r);
|
||||
|
||||
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
|
||||
&& op2 == TREE_OPERAND (exp, 2))
|
||||
|
@ -2045,6 +2033,121 @@ substitute_in_expr (tree exp, tree f, tree r)
|
|||
TREE_READONLY (new) = TREE_READONLY (exp);
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Similar, but look for a PLACEHOLDER_EXPR in EXP and find a replacement
|
||||
for it within OBJ, a tree that is an object or a chain of references. */
|
||||
|
||||
tree
|
||||
substitute_placeholder_in_expr (tree exp, tree obj)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (exp);
|
||||
tree op0, op1, op2;
|
||||
|
||||
/* If this is a PLACEHOLDER_EXPR, see if we find a corresponding type
|
||||
in the chain of OBJ. */
|
||||
if (code == PLACEHOLDER_EXPR)
|
||||
{
|
||||
tree need_type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
|
||||
tree elt;
|
||||
|
||||
for (elt = obj; elt != 0;
|
||||
elt = ((TREE_CODE (elt) == COMPOUND_EXPR
|
||||
|| TREE_CODE (elt) == COND_EXPR)
|
||||
? TREE_OPERAND (elt, 1)
|
||||
: (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
|
||||
? TREE_OPERAND (elt, 0) : 0))
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
|
||||
return elt;
|
||||
|
||||
for (elt = obj; elt != 0;
|
||||
elt = ((TREE_CODE (elt) == COMPOUND_EXPR
|
||||
|| TREE_CODE (elt) == COND_EXPR)
|
||||
? TREE_OPERAND (elt, 1)
|
||||
: (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
|
||||
? TREE_OPERAND (elt, 0) : 0))
|
||||
if (POINTER_TYPE_P (TREE_TYPE (elt))
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
|
||||
== need_type))
|
||||
return fold (build1 (INDIRECT_REF, need_type, elt));
|
||||
|
||||
/* If we didn't find it, return the original PLACEHOLDER_EXPR. If it
|
||||
survives until RTL generation, there will be an error. */
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* TREE_LIST is special because we need to look at TREE_VALUE
|
||||
and TREE_CHAIN, not TREE_OPERANDS. */
|
||||
else if (code == TREE_LIST)
|
||||
{
|
||||
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), obj);
|
||||
op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), obj);
|
||||
if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
|
||||
return exp;
|
||||
|
||||
return tree_cons (TREE_PURPOSE (exp), op1, op0);
|
||||
}
|
||||
else
|
||||
switch (TREE_CODE_CLASS (code))
|
||||
{
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'b':
|
||||
return exp;
|
||||
|
||||
case 'x':
|
||||
case '1':
|
||||
case '2':
|
||||
case '<':
|
||||
case 'e':
|
||||
case 'r':
|
||||
case 's':
|
||||
switch (first_rtl_op (code))
|
||||
{
|
||||
case 0:
|
||||
return exp;
|
||||
|
||||
case 1:
|
||||
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
|
||||
if (op0 == TREE_OPERAND (exp, 0))
|
||||
return exp;
|
||||
else
|
||||
return fold (build1 (code, TREE_TYPE (exp), op0));
|
||||
|
||||
case 2:
|
||||
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
|
||||
op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
|
||||
|
||||
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
|
||||
return exp;
|
||||
else
|
||||
return fold (build2 (code, TREE_TYPE (exp), op0, op1));
|
||||
|
||||
case 3:
|
||||
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
|
||||
op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
|
||||
op2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 2), obj);
|
||||
|
||||
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
|
||||
&& op2 == TREE_OPERAND (exp, 2))
|
||||
return exp;
|
||||
else
|
||||
return fold (build3 (code, TREE_TYPE (exp), op0, op1, op2));
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Stabilize a reference so that we can use it any number of times
|
||||
without causing its operands to be evaluated more than once.
|
||||
|
|
31
gcc/tree.def
31
gcc/tree.def
|
@ -541,35 +541,22 @@ DEFTREECODE (CLEANUP_POINT_EXPR, "cleanup_point_expr", 'e', 1)
|
|||
actual size at run-time. In the following, we describe how this
|
||||
calculation is done.
|
||||
|
||||
When we wish to evaluate a size or offset, we check whether it
|
||||
contains a PLACEHOLDER_EXPR. If it does, we construct a
|
||||
WITH_RECORD_EXPR that contains both the expression we wish to
|
||||
evaluate and an expression within which the object may be found.
|
||||
The latter expression is the object itself in the simple case of an
|
||||
Ada record with discriminant, but it can be the array in the case of
|
||||
an unconstrained array.
|
||||
When we wish to evaluate a size or offset, we check whether it contains a
|
||||
PLACEHOLDER_EXPR. If it does, we call substitute_placeholder_in_expr
|
||||
passing both that tree and an expression within which the object may be
|
||||
found. The latter expression is the object itself in the simple case of
|
||||
an Ada record with discriminant, but it can be the array in the case of an
|
||||
unconstrained array.
|
||||
|
||||
In the latter case, we need the fat pointer, because the bounds of
|
||||
the array can only be accessed from it. However, we rely here on the
|
||||
fact that the expression for the array contains the dereference of
|
||||
the fat pointer that obtained the array pointer.
|
||||
the fat pointer that obtained the array pointer. */
|
||||
|
||||
Accordingly, when looking for the object to substitute in place of
|
||||
a PLACEHOLDER_EXPR, we look down the first operand of the expression
|
||||
passed as the second operand to WITH_RECORD_EXPR until we find
|
||||
something of the desired type or reach a constant. */
|
||||
|
||||
/* Denotes a record to later be supplied with a WITH_RECORD_EXPR when
|
||||
evaluating this expression. The type of this expression is used to
|
||||
find the record to replace it. */
|
||||
/* Denotes a record to later be substitued before evaluating this expression.
|
||||
The type of this expression is used to find the record to replace it. */
|
||||
DEFTREECODE (PLACEHOLDER_EXPR, "placeholder_expr", 'x', 0)
|
||||
|
||||
/* Provide an expression that references a record to be used in place
|
||||
of a PLACEHOLDER_EXPR. The record to be used is the record within
|
||||
operand 1 that has the same type as the PLACEHOLDER_EXPR in
|
||||
operand 0. */
|
||||
DEFTREECODE (WITH_RECORD_EXPR, "with_record_expr", 'e', 2)
|
||||
|
||||
/* Simple arithmetic. */
|
||||
DEFTREECODE (PLUS_EXPR, "plus_expr", '2', 2)
|
||||
DEFTREECODE (MINUS_EXPR, "minus_expr", '2', 2)
|
||||
|
|
18
gcc/tree.h
18
gcc/tree.h
|
@ -2675,6 +2675,24 @@ extern int has_cleanups (tree);
|
|||
|
||||
extern tree substitute_in_expr (tree, tree, tree);
|
||||
|
||||
/* This macro calls the above function but short-circuits the common
|
||||
case of a constant to save time and also checks for NULL. */
|
||||
|
||||
#define SUBSTITUTE_IN_EXPR(EXP, F, R) \
|
||||
((EXP) == 0 || TREE_CONSTANT (EXP) ? (EXP) : substitute_in_expr (EXP, F, R))
|
||||
|
||||
/* Similar, but look for a PLACEHOLDER_EXPR in EXP and find a replacement
|
||||
for it within OBJ, a tree that is an object or a chain of references. */
|
||||
|
||||
extern tree substitute_placeholder_in_expr (tree, tree);
|
||||
|
||||
/* This macro calls the above function but short-circuits the common
|
||||
case of a constant to save time and also checks for NULL. */
|
||||
|
||||
#define SUBSTITUTE_PLACEHOLDER_IN_EXPR(EXP, OBJ) \
|
||||
((EXP) == 0 || TREE_CONSTANT (EXP) ? (EXP) \
|
||||
: substitute_placeholder_in_expr (EXP, OBJ))
|
||||
|
||||
/* variable_size (EXP) is like save_expr (EXP) except that it
|
||||
is for the special case of something that is part of a
|
||||
variable size for a data type. It makes special arrangements
|
||||
|
|
Loading…
Add table
Reference in a new issue