This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: Fix stmtexpr1.C on Thumb
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 31 Dec 2003 10:49:19 -0800
- Subject: PATCH: Fix stmtexpr1.C on Thumb
- Reply-to: mark at codesourcery dot com
This patch fixes a compilation failure on Thumb mode with the C++
stmtexpr1.C test.
When expand_expr sees a VAR_DECL, it will normally just return the
DECL_RTL for the variable. However, if the DECL_RTL is a MEM with an
invalid memory address, it will load the memory address into a
register instead. That can confuse store_expr: if the value returned
by expand_expr is not the target passed in, then store_expr generates
a bitwise copy from the location returned by expand_expr to the
target. Unfortunately, introducing additional bitwise copies in some
languages (C++) isn't valid.
To avoid this problem, store_expr had code that said "if the source
expression is a VAR_DECL, don't generate the copy". Similarly, the C
statement-expression code said "if the last value in the
statement-expression is a VAR_DECL, return its RTL, not the value from
expand_expr". It's not clear that's valid in general; if it's OK to
do that, why is expand_expr bothering to load the address into a
register in the first place?
Futhremore, both pieces of code fail to handle things like "(foo(),
a)" where "a" is a VAR_DECL. More involved situations involving
nested comma-expressions and statement-expressions can arise.
This patch removes the hacks from c_expand_expr, and changes
store_expr to check to see if the target is an invalid memory address.
If so, the copy is not done. If that turns out not to be the right
fix, then the right fix will be to simply have expand_expr return an
indication of whether or not the location it used is in fact
equivalent to the target, rather than trying to divine that in
store_expr.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-12-31 Mark Mitchell <mark@codesourcery.com>
* c-common.c (c_expand_expr): Remove code to return a value
different from that returned by expand_expr.
* expr.c (store_expr): Use the validity of a target MEM, rather
than checking DECL_RTL (exp), to figure out if a copy is
required.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.472
diff -c -5 -p -r1.472 c-common.c
*** c-common.c 25 Dec 2003 16:21:34 -0000 1.472
--- c-common.c 31 Dec 2003 17:13:05 -0000
*************** c_expand_expr (tree exp, rtx target, enu
*** 4062,4072 ****
case STMT_EXPR:
{
tree rtl_expr;
rtx result;
bool preserve_result = false;
- bool return_target = false;
if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx)
{
tree stmt = STMT_EXPR_STMT (exp);
tree scope;
--- 4062,4071 ----
*************** c_expand_expr (tree exp, rtx target, enu
*** 4110,4143 ****
}
if (TREE_CODE (last) == SCOPE_STMT
&& TREE_CODE (expr) == EXPR_STMT)
{
! if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
! && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
! /* If the last expression is a variable whose RTL is the
! same as our target, just return the target; if it
! isn't valid expanding the decl would produce different
! RTL, and store_expr would try to do a copy. */
! return_target = true;
! else
! {
! /* Otherwise, note that we want the value from the last
! expression. */
! TREE_ADDRESSABLE (expr) = 1;
! preserve_result = true;
! }
}
}
expand_stmt (STMT_EXPR_STMT (exp));
expand_end_stmt_expr (rtl_expr);
result = expand_expr (rtl_expr, target, tmode, modifier);
! if (return_target)
! result = target;
! else if (preserve_result && GET_CODE (result) == MEM)
{
if (GET_MODE (result) != BLKmode)
result = copy_to_reg (result);
else
preserve_temp_slots (result);
--- 4109,4130 ----
}
if (TREE_CODE (last) == SCOPE_STMT
&& TREE_CODE (expr) == EXPR_STMT)
{
! /* Otherwise, note that we want the value from the last
! expression. */
! TREE_ADDRESSABLE (expr) = 1;
! preserve_result = true;
}
}
expand_stmt (STMT_EXPR_STMT (exp));
expand_end_stmt_expr (rtl_expr);
result = expand_expr (rtl_expr, target, tmode, modifier);
! if (preserve_result && GET_CODE (result) == MEM)
{
if (GET_MODE (result) != BLKmode)
result = copy_to_reg (result);
else
preserve_temp_slots (result);
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.608
diff -c -5 -p -r1.608 expr.c
*** expr.c 20 Dec 2003 01:40:40 -0000 1.608
--- expr.c 31 Dec 2003 17:13:06 -0000
*************** store_expr (tree exp, rtx target, int wa
*** 4251,4265 ****
if ((! rtx_equal_p (temp, target)
|| (temp != target && (side_effects_p (temp)
|| side_effects_p (target))))
&& TREE_CODE (exp) != ERROR_MARK
&& ! dont_store_target
! /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
! but TARGET is not valid memory reference, TEMP will differ
! from TARGET although it is really the same location. */
! && (TREE_CODE_CLASS (TREE_CODE (exp)) != 'd'
! || target != DECL_RTL_IF_SET (exp))
/* If there's nothing to copy, don't bother. Don't call expr_size
unless necessary, because some front-ends (C++) expr_size-hook
aborts on objects that are not supposed to be bit-copied or
bit-initialized. */
&& expr_size (exp) != const0_rtx)
--- 4251,4267 ----
if ((! rtx_equal_p (temp, target)
|| (temp != target && (side_effects_p (temp)
|| side_effects_p (target))))
&& TREE_CODE (exp) != ERROR_MARK
&& ! dont_store_target
! /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
! but TARGET is not valid memory reference, TEMP will differ
! from TARGET although it is really the same location. */
! && !(GET_CODE (target) == MEM
! && GET_CODE (XEXP (target, 0)) != QUEUED
! && (!memory_address_p (GET_MODE (target), XEXP (target, 0))
! || (flag_force_addr && !REG_P (XEXP (target, 0)))))
/* If there's nothing to copy, don't bother. Don't call expr_size
unless necessary, because some front-ends (C++) expr_size-hook
aborts on objects that are not supposed to be bit-copied or
bit-initialized. */
&& expr_size (exp) != const0_rtx)