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]

Fixing addressof bug.



For the following C++ code

extern void traceIt (  const char *, ...);

class Class1 {
public:
   char num;
   char inst;
};

class GblTable {
 public:
   void   getInfo   (Class1 lpId);
}; 

extern GblTable& lp;
extern Class1 ttt;
void   getInfo   (Class1 lpId);


void crapIt()
{
   Class1 whatzit = ttt;

   if (whatzit.num > 10)
   {
      return;
   }

   lp.getInfo( whatzit );
   traceIt ( "string2",   whatzit.num ) ;
} 

Gcc for i960 generates after the first CSE for whatzit.num:

(insn 15 14 16 (set (reg:SI 44)
        (lshiftrt:SI (reg:SI 45)
            (const_int 24 [0x18]))) 149 {lshrsi3} (nil)
    (expr_list:REG_EQUAL (zero_extend:SI (mem/s:QI (addressof:SI (reg/v:HI 46) 43) 0))
        (nil)))

  (mem/s:HI (addressof:SI (reg/v:HI 46) 43) 0) is only present in RTL
and there are no other occurences (mem/s:QI (addressof:SI (reg/v:HI
46) 43) 0)).  Therefore GCC cannot change (mem/s:QI (addressof:SI
(reg/v:HI 46) 43) 0)) in the note and make abort.  The following patch
solves the problem and also improve code for changing addressof in
notes.  The patch has been commited into egcs repository.


Wed May  5 16:26:13 1999  Vladimir Makarov  <vmakarov@tofu.to.cygnus.com>

	* function.c (purge_addressof_replacements): Rename into
 	purge_bitfield_addressof_replacements.
	(purge_addressof_replacements): New variable.
	(purge_addressof_1): Add code for changing addressof in notes for
 	field values which are extracted by usage MEM with narrower mode.
	(purge_addressof): Initialize purge_bitfield_addressof_replacements.

Index: function.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -p -c -r1.89 -r1.90
*** function.c	1999/04/26 22:51:05	1.89
--- function.c	1999/05/05 13:30:51	1.90
*************** put_addressof_into_stack (r, ht)
*** 3031,3036 ****
--- 3031,3044 ----
  
  /* List of replacements made below in purge_addressof_1 when creating
     bitfield insertions.  */
+ static rtx purge_bitfield_addressof_replacements;
+ 
+ /* List of replacements made below in purge_addressof_1 for patterns
+    (MEM (ADDRESSOF (REG ...))).  The key of the list entry is the
+    corresponding (ADDRESSOF (REG ...)) and value is a substitution for
+    the all pattern.  List PURGE_BITFIELD_ADDRESSOF_REPLACEMENTS is not
+    enough in complex cases, e.g. when some field values can be
+    extracted by usage MEM with narrower mode. */
  static rtx purge_addressof_replacements;
  
  /* Helper function for purge_addressof.  See if the rtx expression at *LOC
*************** purge_addressof_1 (loc, insn, force, sto
*** 3110,3160 ****
  		 was replaced by.  */
  	      rtx tem;
  
! 	      for (tem = purge_addressof_replacements; tem != NULL_RTX;
  		   tem = XEXP (XEXP (tem, 1), 1))
! 		{
! 		  rtx y = XEXP (tem, 0);
! 		  if (GET_CODE (y) == MEM
! 		      && rtx_equal_p (XEXP (x, 0), XEXP (y, 0)))
! 		    {
! 		      /* It can happen that the note may speak of things in
! 			 a wider (or just different) mode than the code did. 
! 			 This is especially true of REG_RETVAL.  */
! 
! 		      rtx z = XEXP (XEXP (tem, 1), 0);
! 		      if (GET_MODE (x) != GET_MODE (y))
! 			{
! 			  if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
! 			    z = SUBREG_REG (z);
! 
! 			  /* ??? If we'd gotten into any of the really complex
! 			     cases below, I'm not sure we can do a proper
! 			     replacement.  Might we be able to delete the
! 			     note in some cases?  */
! 			  if (GET_MODE_SIZE (GET_MODE (x))
! 			      < GET_MODE_SIZE (GET_MODE (y)))
! 			    abort ();
! 
! 			  if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
! 			      && (GET_MODE_SIZE (GET_MODE (x))
! 				  > GET_MODE_SIZE (GET_MODE (z))))
! 			    {
! 			      /* This can occur as a result in invalid
! 				 pointer casts, e.g. float f; ... 
! 				 *(long long int *)&f.
! 				 ??? We could emit a warning here, but
! 				 without a line number that wouldn't be
! 				 very helpful.  */
! 			      z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
! 			    }
! 			  else
! 			    z = gen_lowpart (GET_MODE (x), z);
! 			}
! 
! 		      *loc = z;
! 		      return;
! 		    }
! 		}
  
  	      /* There should always be such a replacement.  */
  	      abort ();
--- 3118,3171 ----
  		 was replaced by.  */
  	      rtx tem;
  
! 	      for (tem = purge_bitfield_addressof_replacements;
! 		   tem != NULL_RTX;
  		   tem = XEXP (XEXP (tem, 1), 1))
! 		if (rtx_equal_p (x, XEXP (tem, 0)))
! 		  {
! 		    *loc = XEXP (XEXP (tem, 1), 0);
! 		    return;
! 		  }
! 
! 	      /* See comment for purge_addressof_replacements. */
! 	      for (tem = purge_addressof_replacements;
! 		   tem != NULL_RTX;
! 		   tem = XEXP (XEXP (tem, 1), 1))
! 		if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
! 		  {
! 		    rtx z = XEXP (XEXP (tem, 1), 0);
! 
! 		    if (GET_MODE (x) == GET_MODE (z)
! 			|| (GET_CODE (XEXP (XEXP (tem, 1), 0)) != REG
! 			    && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
! 		      abort ();
! 
! 		    /* It can happen that the note may speak of things
! 		       in a wider (or just different) mode than the
! 		       code did.  This is especially true of
! 		       REG_RETVAL. */
! 
! 		    if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
! 		      z = SUBREG_REG (z);
! 		    
! 		    if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
! 			&& (GET_MODE_SIZE (GET_MODE (x))
! 			    > GET_MODE_SIZE (GET_MODE (z))))
! 		      {
! 			/* This can occur as a result in invalid
! 			   pointer casts, e.g. float f; ... 
! 			   *(long long int *)&f.
! 			   ??? We could emit a warning here, but
! 			   without a line number that wouldn't be
! 			   very helpful.  */
! 			z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
! 		      }
! 		    else
! 		      z = gen_lowpart (GET_MODE (x), z);
! 
! 		    *loc = z;
! 		    return;
! 		  }
  
  	      /* There should always be such a replacement.  */
  	      abort ();
*************** purge_addressof_1 (loc, insn, force, sto
*** 3242,3251 ****
  
  	      /* Remember the replacement so that the same one can be done
  		 on the REG_NOTES.  */
! 	      purge_addressof_replacements
  		= gen_rtx_EXPR_LIST (VOIDmode, x,
! 				     gen_rtx_EXPR_LIST (VOIDmode, val,
! 							purge_addressof_replacements));
  
  	      /* We replaced with a reg -- all done.  */
  	      return;
--- 3253,3263 ----
  
  	      /* Remember the replacement so that the same one can be done
  		 on the REG_NOTES.  */
! 	      purge_bitfield_addressof_replacements
  		= gen_rtx_EXPR_LIST (VOIDmode, x,
! 				     gen_rtx_EXPR_LIST
! 				     (VOIDmode, val,
! 				      purge_bitfield_addressof_replacements));
  
  	      /* We replaced with a reg -- all done.  */
  	      return;
*************** purge_addressof_1 (loc, insn, force, sto
*** 3255,3264 ****
  	{
  	  /* Remember the replacement so that the same one can be done
  	     on the REG_NOTES.  */
! 	  purge_addressof_replacements
! 	    = gen_rtx_EXPR_LIST (VOIDmode, x,
! 				 gen_rtx_EXPR_LIST (VOIDmode, sub,
! 						    purge_addressof_replacements));
  	  goto restart;
  	}
      give_up:;
--- 3267,3290 ----
  	{
  	  /* Remember the replacement so that the same one can be done
  	     on the REG_NOTES.  */
! 	  if (GET_CODE (sub) == REG || GET_CODE (sub) == SUBREG)
! 	    {
! 	      rtx tem;
! 
! 	      for (tem = purge_addressof_replacements;
! 		   tem != NULL_RTX;
! 		   tem = XEXP (XEXP (tem, 1), 1))
! 		if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
! 		  {
! 		    XEXP (XEXP (tem, 1), 0) = sub;
! 		    return;
! 		  }
! 	      purge_addressof_replacements
! 		= gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0),
! 			   gen_rtx_EXPR_LIST (VOIDmode, sub,
! 					      purge_addressof_replacements));
! 	      return;
! 	    }
  	  goto restart;
  	}
      give_up:;
*************** purge_addressof (insns)
*** 3440,3445 ****
--- 3466,3472 ----
  
    /* Clean up.  */
    hash_table_free (&ht);
+   purge_bitfield_addressof_replacements = 0;
    purge_addressof_replacements = 0;
  }
  


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