tree-def (WITH_SIZE_EXPR): New.

* tree-def (WITH_SIZE_EXPR): New.
        * explow.c (expr_size, int_expr_size): Handle WITH_SIZE_EXPR.
        * expr.c (expand_expr_real_1): Likewise.
        * gimplify.c (maybe_with_size_expr): New.
        (gimplify_arg, gimplify_modify_expr): Use it.
        (gimplify_modify_expr_to_memcpy): Take size parameter.
        (gimplify_modify_expr_to_memset): Likewise.
        (gimplify_expr): Handle WITH_SIZE_EXPR.
        * tree-alias-common.c (find_func_aliases): Likewise.
        * tree-eh.c (tree_could_trap_p): Likewise.
        (tree_could_throw_p): Likewise.
        * tree-gimple.c (is_gimple_lvalue): Likewise.
        (get_call_expr_in): Likewise.
        * tree-inline.c (estimate_num_insns_1): Likewise.
        (expand_calls_inline): Likewise.
        * tree-nested.c (convert_call_expr): Likewise.
        * tree-pretty-print.c (dump_generic_node): Likewise.
        * tree-sra.c (sra_walk_expr): Likewise.
        * tree-ssa-alias.c (add_pointed_to_expr): Likewise.
        * tree-ssa-ccp.c (get_rhs, set_rhs): Likewise.
        * tree-ssa-operands.c (get_expr_operands): Likewise.
        * tree-tailcall.c (find_tail_calls): Likewise.

        * calls.c (expand_call): Reset old_stack_allocated after
        calling emit_stack_restore.

        * gcc.c-torture/compile/20020210-1.c: Remove XFAIL.

From-SVN: r84833
This commit is contained in:
Richard Henderson 2004-07-16 14:13:08 -07:00 committed by Richard Henderson
parent 4c86f32571
commit d25cee4d2b
19 changed files with 225 additions and 68 deletions

View File

@ -1,3 +1,31 @@
2004-07-16 Richard Henderson <rth@redhat.com>
* tree-def (WITH_SIZE_EXPR): New.
* explow.c (expr_size, int_expr_size): Handle WITH_SIZE_EXPR.
* expr.c (expand_expr_real_1): Likewise.
* gimplify.c (maybe_with_size_expr): New.
(gimplify_arg, gimplify_modify_expr): Use it.
(gimplify_modify_expr_to_memcpy): Take size parameter.
(gimplify_modify_expr_to_memset): Likewise.
(gimplify_expr): Handle WITH_SIZE_EXPR.
* tree-alias-common.c (find_func_aliases): Likewise.
* tree-eh.c (tree_could_trap_p): Likewise.
(tree_could_throw_p): Likewise.
* tree-gimple.c (is_gimple_lvalue): Likewise.
(get_call_expr_in): Likewise.
* tree-inline.c (estimate_num_insns_1): Likewise.
(expand_calls_inline): Likewise.
* tree-nested.c (convert_call_expr): Likewise.
* tree-pretty-print.c (dump_generic_node): Likewise.
* tree-sra.c (sra_walk_expr): Likewise.
* tree-ssa-alias.c (add_pointed_to_expr): Likewise.
* tree-ssa-ccp.c (get_rhs, set_rhs): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-tailcall.c (find_tail_calls): Likewise.
* calls.c (expand_call): Reset old_stack_allocated after
calling emit_stack_restore.
2004-07-16 Richard Henderson <rth@redhat.com> 2004-07-16 Richard Henderson <rth@redhat.com>
* langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, * langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING,

View File

@ -3045,6 +3045,7 @@ expand_call (tree exp, rtx target, int ignore)
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
stack_pointer_delta = old_stack_pointer_delta; stack_pointer_delta = old_stack_pointer_delta;
pending_stack_adjust = old_pending_adj; pending_stack_adjust = old_pending_adj;
old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
stack_arg_under_construction = old_stack_arg_under_construction; stack_arg_under_construction = old_stack_arg_under_construction;
highest_outgoing_arg_in_use = initial_highest_arg_in_use; highest_outgoing_arg_in_use = initial_highest_arg_in_use;
stack_usage_map = initial_stack_usage_map; stack_usage_map = initial_stack_usage_map;

View File

@ -240,7 +240,12 @@ eliminate_constant_term (rtx x, rtx *constptr)
rtx rtx
expr_size (tree exp) expr_size (tree exp)
{ {
tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp); tree size;
if (TREE_CODE (exp) == WITH_SIZE_EXPR)
size = TREE_OPERAND (exp, 1);
else
size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0); return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
} }
@ -251,17 +256,17 @@ expr_size (tree exp)
HOST_WIDE_INT HOST_WIDE_INT
int_expr_size (tree exp) int_expr_size (tree exp)
{ {
tree t = lang_hooks.expr_size (exp); tree size;
if (t == 0 if (TREE_CODE (exp) == WITH_SIZE_EXPR)
|| TREE_CODE (t) != INTEGER_CST size = TREE_OPERAND (exp, 1);
|| TREE_OVERFLOW (t) else
|| TREE_INT_CST_HIGH (t) != 0 size = lang_hooks.expr_size (exp);
/* If the result would appear negative, it's too big to represent. */
|| (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0) if (size == 0 || !host_integerp (size, 0))
return -1; return -1;
return TREE_INT_CST_LOW (t); return tree_low_cst (size, 0);
} }
/* Return a copy of X in which all memory references /* Return a copy of X in which all memory references

View File

@ -8651,6 +8651,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
expand_asm_expr (exp); expand_asm_expr (exp);
return const0_rtx; return const0_rtx;
case WITH_SIZE_EXPR:
/* WITH_SIZE_EXPR expands to its first argument. The caller should
have pulled out the size to use in whatever context it needed. */
return expand_expr_real (TREE_OPERAND (exp, 0), original_target, tmode,
modifier, alt_rtl);
default: default:
return lang_hooks.expand_expr (exp, original_target, tmode, return lang_hooks.expand_expr (exp, original_target, tmode,
modifier, alt_rtl); modifier, alt_rtl);

View File

@ -72,8 +72,6 @@ typedef struct gimple_temp_hash_elt
} elt_t; } elt_t;
/* Forward declarations. */ /* Forward declarations. */
static enum gimplify_status gimplify_modify_expr_rhs (tree *, tree *, tree *,
tree *, tree *, bool);
static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool); static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
@ -1788,6 +1786,27 @@ gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p,
} }
} }
/* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
static void
maybe_with_size_expr (tree *expr_p)
{
tree expr, type, size;
expr = *expr_p;
type = TREE_TYPE (expr);
if (type == error_mark_node)
return;
size = TYPE_SIZE_UNIT (type);
if (size && TREE_CODE (size) != INTEGER_CST)
{
size = unshare_expr (size);
size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
*expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
}
}
/* Subroutine of gimplify_call_expr: Gimplify a single argument. */ /* Subroutine of gimplify_call_expr: Gimplify a single argument. */
static enum gimplify_status static enum gimplify_status
@ -1806,6 +1825,9 @@ gimplify_arg (tree *expr_p, tree *pre_p)
else else
test = is_gimple_lvalue, fb = fb_either; test = is_gimple_lvalue, fb = fb_either;
/* If this is a variable sized type, we must remember the size. */
maybe_with_size_expr (expr_p);
/* There is a sequence point before a function call. Side effects in /* There is a sequence point before a function call. Side effects in
the argument list must occur before the actual call. So, when the argument list must occur before the actual call. So, when
gimplifying arguments, force gimplify_expr to use an internal gimplifying arguments, force gimplify_expr to use an internal
@ -2316,18 +2338,14 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
a call to __builtin_memcpy. */ a call to __builtin_memcpy. */
static enum gimplify_status static enum gimplify_status
gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value) gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value)
{ {
tree args, t, to, to_ptr, from; tree args, t, to, to_ptr, from;
to = TREE_OPERAND (*expr_p, 0); to = TREE_OPERAND (*expr_p, 0);
from = TREE_OPERAND (*expr_p, 1); from = TREE_OPERAND (*expr_p, 1);
t = TYPE_SIZE_UNIT (TREE_TYPE (from)); args = tree_cons (NULL, size, NULL);
t = unshare_expr (t);
t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, from);
args = tree_cons (NULL, t, NULL);
t = build_fold_addr_expr (from); t = build_fold_addr_expr (from);
args = tree_cons (NULL, t, args); args = tree_cons (NULL, t, args);
@ -2352,16 +2370,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value)
a CONSTRUCTOR with an empty element list. */ a CONSTRUCTOR with an empty element list. */
static enum gimplify_status static enum gimplify_status
gimplify_modify_expr_to_memset (tree *expr_p, bool want_value) gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value)
{ {
tree args, t, to, to_ptr; tree args, t, to, to_ptr;
to = TREE_OPERAND (*expr_p, 0); to = TREE_OPERAND (*expr_p, 0);
t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (*expr_p, 1))); args = tree_cons (NULL, size, NULL);
t = unshare_expr (t);
t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
args = tree_cons (NULL, t, NULL);
args = tree_cons (NULL, integer_zero_node, args); args = tree_cons (NULL, integer_zero_node, args);
@ -2771,24 +2786,13 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
if (ret != GS_UNHANDLED) if (ret != GS_UNHANDLED)
return ret; return ret;
/* If the value being copied is of variable width, expose the length /* If the value being copied is of variable width, compute the length
if the copy by converting the whole thing to a memcpy/memset. of the copy into a WITH_SIZE_EXPR. Note that we need to do this
Note that we need to do this before gimplifying any of the operands before gimplifying any of the operands so that we can resolve any
so that we can resolve any PLACEHOLDER_EXPRs in the size. PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
Also note that the RTL expander uses the size of the expression to the size of the expression to be copied, not of the destination, so
be copied, not of the destination, so that is what we must here. that is what we must here. */
The types on both sides of the MODIFY_EXPR should be the same, maybe_with_size_expr (from_p);
but they aren't always and there are problems with class-wide types
in Ada where it's hard to make it "correct". */
if (TREE_CODE (TREE_TYPE (*from_p)) != ERROR_MARK
&& TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
&& TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*from_p))) != INTEGER_CST)
{
if (TREE_CODE (*from_p) == CONSTRUCTOR)
return gimplify_modify_expr_to_memset (expr_p, want_value);
else
return gimplify_modify_expr_to_memcpy (expr_p, want_value);
}
ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue); ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
if (ret == GS_ERROR) if (ret == GS_ERROR)
@ -2805,6 +2809,23 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
if (ret != GS_UNHANDLED) if (ret != GS_UNHANDLED)
return ret; return ret;
/* If we've got a variable sized assignment between two lvalues (i.e. does
not involve a call), then we can make things a bit more straightforward
by converting the assignment to memcpy or memset. */
if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
{
tree from = TREE_OPERAND (*from_p, 0);
tree size = TREE_OPERAND (*from_p, 1);
if (TREE_CODE (from) == CONSTRUCTOR)
return gimplify_modify_expr_to_memset (expr_p, size, want_value);
if (is_gimple_addr_expr_arg (from))
{
*from_p = from;
return gimplify_modify_expr_to_memcpy (expr_p, size, want_value);
}
}
/* If the destination is already simple, nothing else needed. */ /* If the destination is already simple, nothing else needed. */
if (is_gimple_tmp_var (*to_p) || !want_value) if (is_gimple_tmp_var (*to_p) || !want_value)
ret = GS_ALL_DONE; ret = GS_ALL_DONE;
@ -3784,6 +3805,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
ret = gimplify_statement_list (expr_p); ret = gimplify_statement_list (expr_p);
break; break;
case WITH_SIZE_EXPR:
{
enum gimplify_status r0, r1;
r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
post_p == &internal_post ? NULL : post_p,
gimple_test_f, fallback);
r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
is_gimple_val, fb_rvalue);
}
break;
case VAR_DECL: case VAR_DECL:
/* ??? If this is a local variable, and it has not been seen in any /* ??? If this is a local variable, and it has not been seen in any
outer BIND_EXPR, then it's probably the result of a duplicate outer BIND_EXPR, then it's probably the result of a duplicate

View File

@ -1,3 +1,7 @@
2004-07-16 Richard Henderson <rth@redhat.com>
* gcc.c-torture/compile/20020210-1.c: Remove XFAIL.
2004-07-16 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de> 2004-07-16 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
* lib/fortran-torture.exp (fortran-torture): Don't test compile * lib/fortran-torture.exp (fortran-torture): Don't test compile

View File

@ -1,3 +1,2 @@
/* PR c/5615 */ /* PR c/5615 */
/* { dg-xfail-if "regression/16417" { "*-*-*" } { "-O1" "-O2" "-O3 -fomit-frame-pointer" "-O3 -g" "-Os" } { "" } } */
void f(int a, struct {int b[a];} c) {} void f(int a, struct {int b[a];} c) {}

View File

@ -448,7 +448,10 @@ find_func_aliases (tree stp)
{ {
op0 = TREE_OPERAND (stp, 0); op0 = TREE_OPERAND (stp, 0);
op1 = TREE_OPERAND (stp, 1); op1 = TREE_OPERAND (stp, 1);
if (TREE_CODE (op1) == WITH_SIZE_EXPR)
op1 = TREE_OPERAND (op1, 0);
} }
/* lhsAV should always have an alias variable */ /* lhsAV should always have an alias variable */
lhsAV = get_alias_var (op0); lhsAV = get_alias_var (op0);
if (!lhsAV) if (!lhsAV)

View File

@ -1723,14 +1723,17 @@ tree_could_trap_p (tree expr)
honor_trapv = true; honor_trapv = true;
} }
restart:
switch (code) switch (code)
{ {
case COMPONENT_REF: case COMPONENT_REF:
case REALPART_EXPR: case REALPART_EXPR:
case IMAGPART_EXPR: case IMAGPART_EXPR:
case BIT_FIELD_REF: case BIT_FIELD_REF:
t = TREE_OPERAND (expr, 0); case WITH_SIZE_EXPR:
return tree_could_trap_p (t); expr = TREE_OPERAND (expr, 0);
code = TREE_CODE (expr);
goto restart;
case ARRAY_RANGE_REF: case ARRAY_RANGE_REF:
/* Let us be conservative here for now. We might be checking bounds of /* Let us be conservative here for now. We might be checking bounds of
@ -1843,6 +1846,8 @@ tree_could_throw_p (tree t)
t = TREE_OPERAND (t, 1); t = TREE_OPERAND (t, 1);
} }
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR) if (TREE_CODE (t) == CALL_EXPR)
return (call_expr_flags (t) & ECF_NOTHROW) == 0; return (call_expr_flags (t) & ECF_NOTHROW) == 0;
if (flag_non_call_exceptions) if (flag_non_call_exceptions)

View File

@ -118,12 +118,22 @@ Boston, MA 02111-1307, USA. */
addr-expr-arg: ID addr-expr-arg: ID
| compref | compref
with-size-arg: addr-expr-arg
| indirectref
| call-stmt
indirectref : INDIRECT_REF
op0 -> val
lhs : addr-expr-arg lhs : addr-expr-arg
| '*' val
| bitfieldref | bitfieldref
| indirectref
| WITH_SIZE_EXPR
op0 -> with-size-arg
op1 -> val
min-lval : ID min-lval : ID
| '*' val | indirectref
bitfieldref : BIT_FIELD_REF bitfieldref : BIT_FIELD_REF
op0 -> inner-compref op0 -> inner-compref
@ -155,18 +165,26 @@ Boston, MA 02111-1307, USA. */
op0 -> inner-compref op0 -> inner-compref
condition : val condition : val
| val RELOP val | RELOP
op0 -> val
op1 -> val
val : ID val : ID
| CONST | CONST
rhs : lhs rhs : lhs
| CONST | CONST
| '&' addr-expr-arg | call-stmt
| call_expr | ADDR_EXPR
| UNOP val op0 -> addr-expr-arg
| val BINOP val | UNOP
| val RELOP val op0 -> val
| BINOP
op0 -> val
op1 -> val
| RELOP
op0 -> val
op1 -> val
*/ */
static inline bool is_gimple_id (tree); static inline bool is_gimple_id (tree);
@ -286,6 +304,7 @@ is_gimple_lvalue (tree t)
{ {
return (is_gimple_addr_expr_arg (t) return (is_gimple_addr_expr_arg (t)
|| TREE_CODE (t) == INDIRECT_REF || TREE_CODE (t) == INDIRECT_REF
|| TREE_CODE (t) == WITH_SIZE_EXPR
/* These are complex lvalues, but don't have addresses, so they /* These are complex lvalues, but don't have addresses, so they
go here. */ go here. */
|| TREE_CODE (t) == BIT_FIELD_REF); || TREE_CODE (t) == BIT_FIELD_REF);
@ -506,6 +525,8 @@ get_call_expr_in (tree t)
{ {
if (TREE_CODE (t) == MODIFY_EXPR) if (TREE_CODE (t) == MODIFY_EXPR)
t = TREE_OPERAND (t, 1); t = TREE_OPERAND (t, 1);
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR) if (TREE_CODE (t) == CALL_EXPR)
return t; return t;
return NULL_TREE; return NULL_TREE;

View File

@ -1262,6 +1262,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
case EXIT_EXPR: case EXIT_EXPR:
case LOOP_EXPR: case LOOP_EXPR:
case PHI_NODE: case PHI_NODE:
case WITH_SIZE_EXPR:
break; break;
/* We don't account constants for now. Assume that the cost is amortized /* We don't account constants for now. Assume that the cost is amortized
@ -1779,6 +1780,11 @@ expand_calls_inline (tree *stmt_p, inline_data *id)
case MODIFY_EXPR: case MODIFY_EXPR:
stmt_p = &TREE_OPERAND (stmt, 1); stmt_p = &TREE_OPERAND (stmt, 1);
stmt = *stmt_p; stmt = *stmt_p;
if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
{
stmt_p = &TREE_OPERAND (stmt, 0);
stmt = *stmt_p;
}
if (TREE_CODE (stmt) != CALL_EXPR) if (TREE_CODE (stmt) != CALL_EXPR)
break; break;

View File

@ -1196,7 +1196,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
case RETURN_EXPR: case RETURN_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
/* Only return and modify may contain calls. */ case WITH_SIZE_EXPR:
/* Only return modify and with_size_expr may contain calls. */
*walk_subtrees = 1; *walk_subtrees = 1;
break; break;

View File

@ -1413,6 +1413,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_decimal_int (buffer, SSA_NAME_VERSION (node)); pp_decimal_int (buffer, SSA_NAME_VERSION (node));
break; break;
case WITH_SIZE_EXPR:
pp_string (buffer, "WITH_SIZE_EXPR <");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
pp_string (buffer, ">");
break;
case VALUE_HANDLE: case VALUE_HANDLE:
pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node)); pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
break; break;

View File

@ -731,6 +731,11 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
type other than the one we've scalarized. */ type other than the one we've scalarized. */
goto use_all; goto use_all;
case WITH_SIZE_EXPR:
/* This is a transparent wrapper. The entire inner expression really
is being used. */
goto use_all;
use_all: use_all:
expr_p = &TREE_OPERAND (inner, 0); expr_p = &TREE_OPERAND (inner, 0);
inner = expr = *expr_p; inner = expr = *expr_p;

View File

@ -1680,6 +1680,9 @@ add_pointed_to_expr (tree ptr, tree value)
{ {
struct ptr_info_def *pi; struct ptr_info_def *pi;
if (TREE_CODE (value) == WITH_SIZE_EXPR)
value = TREE_OPERAND (value, 0);
#if defined ENABLE_CHECKING #if defined ENABLE_CHECKING
/* Pointer variables should have been handled by merge_pointed_to_info. */ /* Pointer variables should have been handled by merge_pointed_to_info. */
if (TREE_CODE (value) == SSA_NAME if (TREE_CODE (value) == SSA_NAME

View File

@ -2085,13 +2085,16 @@ get_rhs (tree stmt)
{ {
case RETURN_EXPR: case RETURN_EXPR:
stmt = TREE_OPERAND (stmt, 0); stmt = TREE_OPERAND (stmt, 0);
if (stmt) if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
return get_rhs (stmt); return stmt;
else /* FALLTHRU */
return NULL;
case MODIFY_EXPR: case MODIFY_EXPR:
return TREE_OPERAND (stmt, 1); stmt = TREE_OPERAND (stmt, 1);
if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
return TREE_OPERAND (stmt, 0);
else
return stmt;
case COND_EXPR: case COND_EXPR:
return COND_EXPR_COND (stmt); return COND_EXPR_COND (stmt);
@ -2143,6 +2146,9 @@ set_rhs (tree *stmt_p, tree expr)
/* FALLTHRU */ /* FALLTHRU */
case MODIFY_EXPR: case MODIFY_EXPR:
op = TREE_OPERAND (stmt, 1);
if (TREE_CODE (op) == WITH_SIZE_EXPR)
stmt = op;
TREE_OPERAND (stmt, 1) = expr; TREE_OPERAND (stmt, 1) = expr;
break; break;

View File

@ -931,23 +931,38 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops); get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops);
return; return;
case WITH_SIZE_EXPR:
/* WITH_SIZE_EXPR is a pass-through reference to it's first argument,
and an rvalue reference to its second argument. */
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops);
return;
case CALL_EXPR: case CALL_EXPR:
get_call_expr_operands (stmt, expr, prev_vops); get_call_expr_operands (stmt, expr, prev_vops);
return; return;
case MODIFY_EXPR: case MODIFY_EXPR:
{
int subflags;
tree op;
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops); get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF op = TREE_OPERAND (expr, 0);
|| TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF if (TREE_CODE (op) == WITH_SIZE_EXPR)
|| TREE_CODE (TREE_OPERAND (expr, 0)) == REALPART_EXPR op = TREE_OPERAND (expr, 0);
|| TREE_CODE (TREE_OPERAND (expr, 0)) == IMAGPART_EXPR) if (TREE_CODE (op) == ARRAY_REF
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def, || TREE_CODE (op) == COMPONENT_REF
prev_vops); || TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
subflags = opf_is_def;
else else
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags = opf_is_def | opf_kill_def;
opf_is_def | opf_kill_def, prev_vops);
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags, prev_vops);
return; return;
}
case VA_ARG_EXPR: case VA_ARG_EXPR:
/* Mark VA_ARG_EXPR nodes as making volatile references. FIXME, /* Mark VA_ARG_EXPR nodes as making volatile references. FIXME,

View File

@ -384,6 +384,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
{ {
ass_var = TREE_OPERAND (stmt, 0); ass_var = TREE_OPERAND (stmt, 0);
call = TREE_OPERAND (stmt, 1); call = TREE_OPERAND (stmt, 1);
if (TREE_CODE (call) == WITH_SIZE_EXPR)
call = TREE_OPERAND (call, 0);
} }
else else
{ {

View File

@ -885,6 +885,13 @@ DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0)
baseclass of itself or another class. */ baseclass of itself or another class. */
DEFTREECODE (TREE_BINFO, "tree_binfo", 'x', 0) DEFTREECODE (TREE_BINFO, "tree_binfo", 'x', 0)
/* Records the size for an expression of variable size type. This is
for use in contexts in which we are accessing the entire object,
such as for a function call, or block copy.
Operand 0 is the real expression.
Operand 1 is the size of the type in the expression. */
DEFTREECODE (WITH_SIZE_EXPR, "with_size_expr", 'e', 2)
/* /*
Local variables: Local variables:
mode:c mode:c