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
This commit is contained in:
parent
6180abdb9d
commit
1574ef130f
8 changed files with 124 additions and 41 deletions
|
@ -1,3 +1,24 @@
|
|||
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>
|
||||
|
||||
* configure.in: Prepend ${srcdir}/config/${cpu_type}/ instead of
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Subroutines shared by all languages that are variants of C.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
|
@ -3418,6 +3418,27 @@ c_expand_expr (exp, target, tmode, modifier)
|
|||
STMT_EXPR. */
|
||||
push_temp_slots ();
|
||||
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_end_stmt_expr (rtl_expr);
|
||||
result = expand_expr (rtl_expr, target, tmode, modifier);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Definitions for c-common.c.
|
||||
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.
|
||||
|
||||
|
@ -717,6 +717,7 @@ extern void add_c_tree_codes PARAMS ((void));
|
|||
extern void genrtl_do_pushlevel PARAMS ((void));
|
||||
extern void genrtl_goto_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_if_stmt PARAMS ((tree));
|
||||
extern void genrtl_while_stmt PARAMS ((tree));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* This file contains the definitions and documentation for the common
|
||||
tree codes used in the GNU C and C++ compilers (see c-common.def
|
||||
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).
|
||||
|
||||
This file is part of GCC.
|
||||
|
@ -305,11 +305,26 @@ genrtl_goto_stmt (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)
|
||||
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)
|
||||
{
|
||||
|
@ -319,7 +334,7 @@ genrtl_expr_stmt (expr)
|
|||
expand_start_target_temps ();
|
||||
|
||||
if (expr != error_mark_node)
|
||||
expand_expr_stmt (expr);
|
||||
expand_expr_stmt_value (expr, want_value);
|
||||
|
||||
if (stmts_are_full_exprs_p ())
|
||||
expand_end_target_temps ();
|
||||
|
@ -748,7 +763,7 @@ expand_stmt (t)
|
|||
break;
|
||||
|
||||
case EXPR_STMT:
|
||||
genrtl_expr_stmt (EXPR_STMT_EXPR (t));
|
||||
genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t));
|
||||
break;
|
||||
|
||||
case DECL_STMT:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Convert tree expression to rtl instructions, for GNU compiler.
|
||||
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.
|
||||
|
||||
|
@ -6453,7 +6453,7 @@ expand_expr (exp, target, tmode, modifier)
|
|||
|
||||
case LABELED_BLOCK_EXPR:
|
||||
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. */
|
||||
do_pending_stack_adjust ();
|
||||
emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
|
||||
|
@ -6468,7 +6468,7 @@ expand_expr (exp, target, tmode, modifier)
|
|||
case LOOP_EXPR:
|
||||
push_temp_slots ();
|
||||
expand_start_loop (1);
|
||||
expand_expr_stmt (TREE_OPERAND (exp, 0));
|
||||
expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0);
|
||||
expand_end_loop ();
|
||||
pop_temp_slots ();
|
||||
|
||||
|
|
67
gcc/stmt.c
67
gcc/stmt.c
|
@ -1,6 +1,6 @@
|
|||
/* Expands front end tree to back end RTL for GNU C-Compiler
|
||||
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.
|
||||
|
||||
|
@ -2182,16 +2182,37 @@ resolve_operand_name_1 (p, outputs, inputs)
|
|||
}
|
||||
|
||||
/* 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
|
||||
expand_expr_stmt (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,
|
||||
except for an explicit cast to void (e.g. for assert()), and
|
||||
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))
|
||||
{
|
||||
|
@ -2207,34 +2228,31 @@ expand_expr_stmt (exp)
|
|||
|
||||
/* If EXP is of function type and we are expanding statements for
|
||||
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);
|
||||
|
||||
/* The call to `expand_expr' could cause last_expr_type and
|
||||
last_expr_value to get reset. Therefore, we set last_expr_value
|
||||
and last_expr_type *after* calling expand_expr. */
|
||||
last_expr_value = expand_expr (exp,
|
||||
(expr_stmts_for_value
|
||||
? NULL_RTX : const0_rtx),
|
||||
VOIDmode, 0);
|
||||
last_expr_type = TREE_TYPE (exp);
|
||||
value = expand_expr (exp, want_value ? NULL_RTX : const0_rtx,
|
||||
VOIDmode, 0);
|
||||
type = TREE_TYPE (exp);
|
||||
|
||||
/* If all we do is reference a volatile value in memory,
|
||||
copy it to a register to be sure it is actually touched. */
|
||||
if (last_expr_value != 0 && GET_CODE (last_expr_value) == MEM
|
||||
&& TREE_THIS_VOLATILE (exp))
|
||||
if (value && GET_CODE (value) == MEM && TREE_THIS_VOLATILE (exp))
|
||||
{
|
||||
if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode)
|
||||
if (TYPE_MODE (type) == VOIDmode)
|
||||
;
|
||||
else if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
|
||||
copy_to_reg (last_expr_value);
|
||||
else if (TYPE_MODE (type) != BLKmode)
|
||||
value = copy_to_reg (value);
|
||||
else
|
||||
{
|
||||
rtx lab = gen_label_rtx ();
|
||||
|
||||
/* Compare the value with itself to reference it. */
|
||||
emit_cmp_and_jump_insns (last_expr_value, last_expr_value, EQ,
|
||||
expand_expr (TYPE_SIZE (last_expr_type),
|
||||
emit_cmp_and_jump_insns (value, value, EQ,
|
||||
expand_expr (TYPE_SIZE (type),
|
||||
NULL_RTX, VOIDmode, 0),
|
||||
BLKmode, 0, lab);
|
||||
emit_label (lab);
|
||||
|
@ -2243,13 +2261,19 @@ expand_expr_stmt (exp)
|
|||
|
||||
/* If this expression is part of a ({...}) and is in memory, we may have
|
||||
to preserve temporaries. */
|
||||
preserve_temp_slots (last_expr_value);
|
||||
preserve_temp_slots (value);
|
||||
|
||||
/* Free any temporaries used to evaluate this expression. Any temporary
|
||||
used as a result of this expression will already have been preserved
|
||||
above. */
|
||||
free_temp_slots ();
|
||||
|
||||
if (want_value)
|
||||
{
|
||||
last_expr_value = value;
|
||||
last_expr_type = type;
|
||||
}
|
||||
|
||||
emit_queue ();
|
||||
}
|
||||
|
||||
|
@ -2386,6 +2410,7 @@ expand_start_stmt_expr ()
|
|||
start_sequence_for_rtl_expr (t);
|
||||
NO_DEFER_POP;
|
||||
expr_stmts_for_value++;
|
||||
last_expr_value = NULL_RTX;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -2407,15 +2432,11 @@ expand_end_stmt_expr (t)
|
|||
{
|
||||
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_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))
|
||||
/* Remove any possible QUEUED. */
|
||||
last_expr_value = protect_from_queue (last_expr_value, 0);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 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>
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
@ -624,7 +624,9 @@ declare_return_variable (id, use_stmt)
|
|||
*use_stmt = build_stmt (EXPR_STMT,
|
||||
build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
|
||||
var));
|
||||
|
||||
|
||||
TREE_ADDRESSABLE (*use_stmt) = 1;
|
||||
|
||||
/* Build the declaration statement if FN does not return an
|
||||
aggregate. */
|
||||
if (need_return_decl)
|
||||
|
|
12
gcc/tree.h
12
gcc/tree.h
|
@ -1,6 +1,6 @@
|
|||
/* Front-end tree definitions for GNU compiler.
|
||||
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
|
@ -161,7 +161,9 @@ struct tree_common
|
|||
|
||||
TREE_ADDRESSABLE in
|
||||
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:
|
||||
|
||||
|
@ -258,8 +260,7 @@ struct tree_common
|
|||
expressions, VAR_DECL, PARM_DECL, FIELD_DECL, FUNCTION_DECL,
|
||||
IDENTIFIER_NODE
|
||||
TYPE_BOUNDED in
|
||||
..._TYPE
|
||||
*/
|
||||
..._TYPE */
|
||||
|
||||
/* Define accessors for the fields that all tree nodes have
|
||||
(though some fields are not used for all kinds of nodes). */
|
||||
|
@ -2719,6 +2720,7 @@ extern void expand_fixups PARAMS ((rtx));
|
|||
extern tree expand_start_stmt_expr PARAMS ((void));
|
||||
extern tree expand_end_stmt_expr 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 void expand_decl_init PARAMS ((tree));
|
||||
extern void clear_last_expr PARAMS ((void));
|
||||
|
|
Loading…
Add table
Reference in a new issue