This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Fix stmtexpr1.C on Thumb


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]