Commit 1574ef13 by Alexandre Oliva Committed by Alexandre Oliva

c-common.h (genrtl_expr_stmt_value): Declare.

* c-common.h (genrtl_expr_stmt_value): Declare.
* c-semantics.c (genrtl_goto_stmt): Redirect to...
(genrtl_goto_stmt_value): ... this new function.  Pass new
argument down to expand_expr_stmt_value, taking
TREE_ADDRESSABLE into account.
* c-common.c (c_expand_expr): Mark the last EXPR_STMT of a
STMT_EXPR as addressable, i.e., one whose result we want.
* expr.c (expand_expr): Don't save expression statement value
of labeled_blocks or loop_exprs.
* stmt.c (expand_expr_stmt): Redirect to...
(expand_expr_stmt_value): ... this new function.  Use new
argument to tell whether to save expression value.
(expand_end_stmt_expr): Reset last_expr_type and
last_expr_value if we don't have either.
* tree-inline.c (declare_return_variable): Mark its use
statement as addressable.
* tree.h: Document new use of TREE_ADDRESSABLE.
(expand_expr_stmt_value): Declare.

From-SVN: r48456
parent 6180abdb
2002-01-02 Alexandre Oliva <aoliva@redhat.com>
* c-common.h (genrtl_expr_stmt_value): Declare.
* c-semantics.c (genrtl_goto_stmt): Redirect to...
(genrtl_goto_stmt_value): ... this new function. Pass new
argument down to expand_expr_stmt_value, taking
TREE_ADDRESSABLE into account.
* c-common.c (c_expand_expr): Mark the last EXPR_STMT of a
STMT_EXPR as addressable, i.e., one whose result we want.
* expr.c (expand_expr): Don't save expression statement value
of labeled_blocks or loop_exprs.
* stmt.c (expand_expr_stmt): Redirect to...
(expand_expr_stmt_value): ... this new function. Use new
argument to tell whether to save expression value.
(expand_end_stmt_expr): Reset last_expr_type and
last_expr_value if we don't have either.
* tree-inline.c (declare_return_variable): Mark its use
statement as addressable.
* tree.h: Document new use of TREE_ADDRESSABLE.
(expand_expr_stmt_value): Declare.
2002-01-01 Joseph S. Myers <jsm28@cam.ac.uk> 2002-01-01 Joseph S. Myers <jsm28@cam.ac.uk>
* configure.in: Prepend ${srcdir}/config/${cpu_type}/ instead of * configure.in: Prepend ${srcdir}/config/${cpu_type}/ instead of
......
/* Subroutines shared by all languages that are variants of C. /* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
Free Software Foundation, Inc. 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -3418,6 +3418,27 @@ c_expand_expr (exp, target, tmode, modifier) ...@@ -3418,6 +3418,27 @@ c_expand_expr (exp, target, tmode, modifier)
STMT_EXPR. */ STMT_EXPR. */
push_temp_slots (); push_temp_slots ();
rtl_expr = expand_start_stmt_expr (); rtl_expr = expand_start_stmt_expr ();
/* If we want the result of this expression, find the last
EXPR_STMT in the COMPOUND_STMT and mark it as addressable. */
if (target != const0_rtx
&& TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT
&& TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT)
{
tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp));
tree last = TREE_CHAIN (expr);
while (TREE_CHAIN (last))
{
expr = last;
last = TREE_CHAIN (last);
}
if (TREE_CODE (last) == SCOPE_STMT
&& TREE_CODE (expr) == EXPR_STMT)
TREE_ADDRESSABLE (expr) = 1;
}
expand_stmt (STMT_EXPR_STMT (exp)); expand_stmt (STMT_EXPR_STMT (exp));
expand_end_stmt_expr (rtl_expr); expand_end_stmt_expr (rtl_expr);
result = expand_expr (rtl_expr, target, tmode, modifier); result = expand_expr (rtl_expr, target, tmode, modifier);
......
/* Definitions for c-common.c. /* Definitions for c-common.c.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998, Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc. 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -717,6 +717,7 @@ extern void add_c_tree_codes PARAMS ((void)); ...@@ -717,6 +717,7 @@ extern void add_c_tree_codes PARAMS ((void));
extern void genrtl_do_pushlevel PARAMS ((void)); extern void genrtl_do_pushlevel PARAMS ((void));
extern void genrtl_goto_stmt PARAMS ((tree)); extern void genrtl_goto_stmt PARAMS ((tree));
extern void genrtl_expr_stmt PARAMS ((tree)); extern void genrtl_expr_stmt PARAMS ((tree));
extern void genrtl_expr_stmt_value PARAMS ((tree, int));
extern void genrtl_decl_stmt PARAMS ((tree)); extern void genrtl_decl_stmt PARAMS ((tree));
extern void genrtl_if_stmt PARAMS ((tree)); extern void genrtl_if_stmt PARAMS ((tree));
extern void genrtl_while_stmt PARAMS ((tree)); extern void genrtl_while_stmt PARAMS ((tree));
......
/* This file contains the definitions and documentation for the common /* This file contains the definitions and documentation for the common
tree codes used in the GNU C and C++ compilers (see c-common.def tree codes used in the GNU C and C++ compilers (see c-common.def
for the standard codes). for the standard codes).
Copyright (C) 2000, 2001 Free Software Foundation, Inc. Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Benjamin Chelf (chelf@codesourcery.com). Written by Benjamin Chelf (chelf@codesourcery.com).
This file is part of GCC. This file is part of GCC.
...@@ -305,12 +305,27 @@ genrtl_goto_stmt (destination) ...@@ -305,12 +305,27 @@ genrtl_goto_stmt (destination)
expand_computed_goto (destination); expand_computed_goto (destination);
} }
/* Generate the RTL for EXPR, which is an EXPR_STMT. */ /* Generate the RTL for EXPR, which is an EXPR_STMT. Provided just
for backward compatibility. genrtl_expr_stmt_value() should be
used for new code. */
void void
genrtl_expr_stmt (expr) genrtl_expr_stmt (expr)
tree expr; tree expr;
{ {
genrtl_expr_stmt_value (expr, -1);
}
/* Generate the RTL for EXPR, which is an EXPR_STMT. WANT_VALUE tells
whether to (1) save the value of the expression, (0) discard it or
(-1) use expr_stmts_for_value to tell. The use of -1 is
deprecated, and retained only for backward compatibility. */
void
genrtl_expr_stmt_value (expr, want_value)
tree expr;
int want_value;
{
if (expr != NULL_TREE) if (expr != NULL_TREE)
{ {
emit_line_note (input_filename, lineno); emit_line_note (input_filename, lineno);
...@@ -319,7 +334,7 @@ genrtl_expr_stmt (expr) ...@@ -319,7 +334,7 @@ genrtl_expr_stmt (expr)
expand_start_target_temps (); expand_start_target_temps ();
if (expr != error_mark_node) if (expr != error_mark_node)
expand_expr_stmt (expr); expand_expr_stmt_value (expr, want_value);
if (stmts_are_full_exprs_p ()) if (stmts_are_full_exprs_p ())
expand_end_target_temps (); expand_end_target_temps ();
...@@ -748,7 +763,7 @@ expand_stmt (t) ...@@ -748,7 +763,7 @@ expand_stmt (t)
break; break;
case EXPR_STMT: case EXPR_STMT:
genrtl_expr_stmt (EXPR_STMT_EXPR (t)); genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t));
break; break;
case DECL_STMT: case DECL_STMT:
......
/* Convert tree expression to rtl instructions, for GNU compiler. /* Convert tree expression to rtl instructions, for GNU compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001 Free Software Foundation, Inc. 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -6453,7 +6453,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -6453,7 +6453,7 @@ expand_expr (exp, target, tmode, modifier)
case LABELED_BLOCK_EXPR: case LABELED_BLOCK_EXPR:
if (LABELED_BLOCK_BODY (exp)) if (LABELED_BLOCK_BODY (exp))
expand_expr_stmt (LABELED_BLOCK_BODY (exp)); expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0);
/* Should perhaps use expand_label, but this is simpler and safer. */ /* Should perhaps use expand_label, but this is simpler and safer. */
do_pending_stack_adjust (); do_pending_stack_adjust ();
emit_label (label_rtx (LABELED_BLOCK_LABEL (exp))); emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
...@@ -6468,7 +6468,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -6468,7 +6468,7 @@ expand_expr (exp, target, tmode, modifier)
case LOOP_EXPR: case LOOP_EXPR:
push_temp_slots (); push_temp_slots ();
expand_start_loop (1); expand_start_loop (1);
expand_expr_stmt (TREE_OPERAND (exp, 0)); expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0);
expand_end_loop (); expand_end_loop ();
pop_temp_slots (); pop_temp_slots ();
......
/* Expands front end tree to back end RTL for GNU C-Compiler /* Expands front end tree to back end RTL for GNU C-Compiler
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001 Free Software Foundation, Inc. 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -2182,16 +2182,37 @@ resolve_operand_name_1 (p, outputs, inputs) ...@@ -2182,16 +2182,37 @@ resolve_operand_name_1 (p, outputs, inputs)
} }
/* Generate RTL to evaluate the expression EXP /* Generate RTL to evaluate the expression EXP
and remember it in case this is the VALUE in a ({... VALUE; }) constr. */ and remember it in case this is the VALUE in a ({... VALUE; }) constr.
Provided just for backward-compatibility. expand_expr_stmt_value()
should be used for new code. */
void void
expand_expr_stmt (exp) expand_expr_stmt (exp)
tree exp; tree exp;
{ {
expand_expr_stmt_value (exp, -1);
}
/* Generate RTL to evaluate the expression EXP. WANT_VALUE tells
whether to (1) save the value of the expression, (0) discard it or
(-1) use expr_stmts_for_value to tell. The use of -1 is
deprecated, and retained only for backward compatibility. */
void
expand_expr_stmt_value (exp, want_value)
tree exp;
int want_value;
{
rtx value;
tree type;
if (want_value == -1)
want_value = expr_stmts_for_value != 0;
/* If -W, warn about statements with no side effects, /* If -W, warn about statements with no side effects,
except for an explicit cast to void (e.g. for assert()), and except for an explicit cast to void (e.g. for assert()), and
except inside a ({...}) where they may be useful. */ except inside a ({...}) where they may be useful. */
if (expr_stmts_for_value == 0 && exp != error_mark_node) if (! want_value && exp != error_mark_node)
{ {
if (! TREE_SIDE_EFFECTS (exp)) if (! TREE_SIDE_EFFECTS (exp))
{ {
...@@ -2207,34 +2228,31 @@ expand_expr_stmt (exp) ...@@ -2207,34 +2228,31 @@ expand_expr_stmt (exp)
/* If EXP is of function type and we are expanding statements for /* If EXP is of function type and we are expanding statements for
value, convert it to pointer-to-function. */ value, convert it to pointer-to-function. */
if (expr_stmts_for_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE) if (want_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp); exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
/* The call to `expand_expr' could cause last_expr_type and /* The call to `expand_expr' could cause last_expr_type and
last_expr_value to get reset. Therefore, we set last_expr_value last_expr_value to get reset. Therefore, we set last_expr_value
and last_expr_type *after* calling expand_expr. */ and last_expr_type *after* calling expand_expr. */
last_expr_value = expand_expr (exp, value = expand_expr (exp, want_value ? NULL_RTX : const0_rtx,
(expr_stmts_for_value
? NULL_RTX : const0_rtx),
VOIDmode, 0); VOIDmode, 0);
last_expr_type = TREE_TYPE (exp); type = TREE_TYPE (exp);
/* If all we do is reference a volatile value in memory, /* If all we do is reference a volatile value in memory,
copy it to a register to be sure it is actually touched. */ copy it to a register to be sure it is actually touched. */
if (last_expr_value != 0 && GET_CODE (last_expr_value) == MEM if (value && GET_CODE (value) == MEM && TREE_THIS_VOLATILE (exp))
&& TREE_THIS_VOLATILE (exp))
{ {
if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode) if (TYPE_MODE (type) == VOIDmode)
; ;
else if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode) else if (TYPE_MODE (type) != BLKmode)
copy_to_reg (last_expr_value); value = copy_to_reg (value);
else else
{ {
rtx lab = gen_label_rtx (); rtx lab = gen_label_rtx ();
/* Compare the value with itself to reference it. */ /* Compare the value with itself to reference it. */
emit_cmp_and_jump_insns (last_expr_value, last_expr_value, EQ, emit_cmp_and_jump_insns (value, value, EQ,
expand_expr (TYPE_SIZE (last_expr_type), expand_expr (TYPE_SIZE (type),
NULL_RTX, VOIDmode, 0), NULL_RTX, VOIDmode, 0),
BLKmode, 0, lab); BLKmode, 0, lab);
emit_label (lab); emit_label (lab);
...@@ -2243,13 +2261,19 @@ expand_expr_stmt (exp) ...@@ -2243,13 +2261,19 @@ expand_expr_stmt (exp)
/* If this expression is part of a ({...}) and is in memory, we may have /* If this expression is part of a ({...}) and is in memory, we may have
to preserve temporaries. */ to preserve temporaries. */
preserve_temp_slots (last_expr_value); preserve_temp_slots (value);
/* Free any temporaries used to evaluate this expression. Any temporary /* Free any temporaries used to evaluate this expression. Any temporary
used as a result of this expression will already have been preserved used as a result of this expression will already have been preserved
above. */ above. */
free_temp_slots (); free_temp_slots ();
if (want_value)
{
last_expr_value = value;
last_expr_type = type;
}
emit_queue (); emit_queue ();
} }
...@@ -2386,6 +2410,7 @@ expand_start_stmt_expr () ...@@ -2386,6 +2410,7 @@ expand_start_stmt_expr ()
start_sequence_for_rtl_expr (t); start_sequence_for_rtl_expr (t);
NO_DEFER_POP; NO_DEFER_POP;
expr_stmts_for_value++; expr_stmts_for_value++;
last_expr_value = NULL_RTX;
return t; return t;
} }
...@@ -2407,15 +2432,11 @@ expand_end_stmt_expr (t) ...@@ -2407,15 +2432,11 @@ expand_end_stmt_expr (t)
{ {
OK_DEFER_POP; OK_DEFER_POP;
if (last_expr_type == 0) if (! last_expr_value || ! last_expr_type)
{ {
last_expr_type = void_type_node;
last_expr_value = const0_rtx; last_expr_value = const0_rtx;
last_expr_type = void_type_node;
} }
else if (last_expr_value == 0)
/* There are some cases where this can happen, such as when the
statement is void type. */
last_expr_value = const0_rtx;
else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value)) else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value))
/* Remove any possible QUEUED. */ /* Remove any possible QUEUED. */
last_expr_value = protect_from_queue (last_expr_value, 0); last_expr_value = protect_from_queue (last_expr_value, 0);
......
/* Control and data flow functions for trees. /* Control and data flow functions for trees.
Copyright 2001 Free Software Foundation, Inc. Copyright 2001, 2002 Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com> Contributed by Alexandre Oliva <aoliva@redhat.com>
This file is part of GNU CC. This file is part of GNU CC.
...@@ -625,6 +625,8 @@ declare_return_variable (id, use_stmt) ...@@ -625,6 +625,8 @@ declare_return_variable (id, use_stmt)
build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
var)); var));
TREE_ADDRESSABLE (*use_stmt) = 1;
/* Build the declaration statement if FN does not return an /* Build the declaration statement if FN does not return an
aggregate. */ aggregate. */
if (need_return_decl) if (need_return_decl)
......
/* Front-end tree definitions for GNU compiler. /* Front-end tree definitions for GNU compiler.
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
Free Software Foundation, Inc. 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -161,7 +161,9 @@ struct tree_common ...@@ -161,7 +161,9 @@ struct tree_common
TREE_ADDRESSABLE in TREE_ADDRESSABLE in
VAR_DECL, FUNCTION_DECL, FIELD_DECL, CONSTRUCTOR, LABEL_DECL, VAR_DECL, FUNCTION_DECL, FIELD_DECL, CONSTRUCTOR, LABEL_DECL,
..._TYPE, IDENTIFIER_NODE ..._TYPE, IDENTIFIER_NODE.
In a STMT_EXPR, it means we want the result of the enclosed
expression.
static_flag: static_flag:
...@@ -258,8 +260,7 @@ struct tree_common ...@@ -258,8 +260,7 @@ struct tree_common
expressions, VAR_DECL, PARM_DECL, FIELD_DECL, FUNCTION_DECL, expressions, VAR_DECL, PARM_DECL, FIELD_DECL, FUNCTION_DECL,
IDENTIFIER_NODE IDENTIFIER_NODE
TYPE_BOUNDED in TYPE_BOUNDED in
..._TYPE ..._TYPE */
*/
/* Define accessors for the fields that all tree nodes have /* Define accessors for the fields that all tree nodes have
(though some fields are not used for all kinds of nodes). */ (though some fields are not used for all kinds of nodes). */
...@@ -2719,6 +2720,7 @@ extern void expand_fixups PARAMS ((rtx)); ...@@ -2719,6 +2720,7 @@ extern void expand_fixups PARAMS ((rtx));
extern tree expand_start_stmt_expr PARAMS ((void)); extern tree expand_start_stmt_expr PARAMS ((void));
extern tree expand_end_stmt_expr PARAMS ((tree)); extern tree expand_end_stmt_expr PARAMS ((tree));
extern void expand_expr_stmt PARAMS ((tree)); extern void expand_expr_stmt PARAMS ((tree));
extern void expand_expr_stmt_value PARAMS ((tree, int));
extern int warn_if_unused_value PARAMS ((tree)); extern int warn_if_unused_value PARAMS ((tree));
extern void expand_decl_init PARAMS ((tree)); extern void expand_decl_init PARAMS ((tree));
extern void clear_last_expr PARAMS ((void)); extern void clear_last_expr PARAMS ((void));
......
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