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]

Re: Fix stack corruption in regrename


On Aug 28, 2001, Bernd Schmidt <bernds@redhat.com> wrote:

> On 28 Aug 2001, Alexandre Oliva wrote:
>> On Aug 27, 2001, Bernd Schmidt <bernds@redhat.com> wrote:
>> 
>> > On 27 Aug 2001, Alexandre Oliva wrote:
>> >> This is still unreviewed.  It's too late for 3.0.1, but it would be
>> >> nice to fix this stack-corruption problem for 3.0.2.
>> >>
>> >> http://gcc.gnu.org/ml/gcc-patches/2001-08/msg00024.html
>> 
>> > Oh, sorry.  The patch is ok; 3.1 and 3.0.
>> 
>> Thanks.  My pre-check-in test passed in mainline, but bootstrap failed
>> in the 3.0 branch.  regmove marks insns with QImode and HImode in
>> certain cases, and it happened to mark a USE insn as such, which
>> caused the following sanity check to fail while compiling c-lex.c for
>> stage2 on i686-pc-linux-gnu.  I don't see where the difference between
>> 3.0 and 3.1 stems from; the code in regmove appears identical, and it
>> doesn't appear to care at all about cleaning up modes of insns.
>> 
>> What should I do now, just hold off from installing this in 3.0?  Is
>> this still ok for 3.1?

> Just add a piece of code that clears all insn modes at the start of
> reload.

Done.  Here are the patches I'm about to check in in 3.0 branch and
mainline, respectively.  Both were bootstrapped and regression tested
on i686-pc-linux-gnu, without regressions.

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* reload.c (find_reloads): Mark new USE insns with QImode.
	(find_reloads_toplev, find_reloads_address, subst_reg_equivs,
	find_reloads_subreg_address): Likewise.
	* regrename.c (note_sets, clear_dead_regs): Abort if pseudos are
	encountered.
	* reload1.c (reload_combine_note_use): Likewise, inside USEs and
	CLOBBERs.
	(reload): Make sure there are no USEs with mode other than
	VOIDmode.  At the end, remove those marked with QImode.

Index: gcc/regrename.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/regrename.c,v
retrieving revision 1.20.4.3
diff -u -p -r1.20.4.3 regrename.c
--- gcc/regrename.c 2001/07/22 07:09:45 1.20.4.3
+++ gcc/regrename.c 2001/09/29 19:17:49
@@ -112,6 +112,11 @@ note_sets (x, set, data)
     return;
   regno = REGNO (x);
   nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+  /* There must not be pseudos at this point.  */
+  if (regno + nregs > FIRST_PSEUDO_REGISTER)
+    abort ();
+
   while (nregs-- > 0)
     SET_HARD_REG_BIT (*pset, regno + nregs);
 }
@@ -132,6 +137,11 @@ clear_dead_regs (pset, kind, notes)
 	rtx reg = XEXP (note, 0);
 	unsigned int regno = REGNO (reg);
 	int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+
+	/* There must not be pseudos at this point.  */
+	if (regno + nregs > FIRST_PSEUDO_REGISTER)
+	  abort ();
+
 	while (nregs-- > 0)
 	  CLEAR_HARD_REG_BIT (*pset, regno + nregs);
       }
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.142.4.2
diff -u -p -r1.142.4.2 reload.c
--- gcc/reload.c 2001/07/23 22:41:47 1.142.4.2
+++ gcc/reload.c 2001/09/29 19:17:50
@@ -3770,7 +3770,11 @@ find_reloads (insn, replace, ind_levels,
 	    if (GET_CODE (operand) == REG)
 	      {
 		if (modified[i] != RELOAD_WRITE)
-		  emit_insn_before (gen_rtx_USE (VOIDmode, operand), insn);
+		  /* We mark the USE with QImode so that we recognize
+		     it as one that can be safely deleted at the end
+		     of reload.  */
+		  PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, operand),
+					      insn), QImode);
 		if (modified[i] != RELOAD_READ)
 		  emit_insn_after (gen_rtx_CLOBBER (VOIDmode, operand), insn);
 	      }
@@ -4256,7 +4260,11 @@ find_reloads_toplev (x, opnum, type, ind
 		 this substitution.  We have to emit a USE of the pseudo so
 		 that delete_output_reload can see it.  */
 	      if (replace_reloads && recog_data.operand[opnum] != x)
-		emit_insn_before (gen_rtx_USE (VOIDmode, x), insn);
+		/* We mark the USE with QImode so that we recognize it
+		   as one that can be safely deleted at the end of
+		   reload.  */
+		PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn),
+			  QImode);
 	      x = mem;
 	      i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
 					opnum, type, ind_levels, insn);
@@ -4529,7 +4537,12 @@ find_reloads_address (mode, memrefloc, a
 		      && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
 		    {
 		      *loc = tem;
-		      emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+		      /* We mark the USE with QImode so that we
+			 recognize it as one that can be safely
+			 deleted at the end of reload.  */
+		      PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, ad),
+						  insn), QImode);
+
 		      /* This doesn't really count as replacing the address
 			 as a whole, since it is still a memory access.  */
 		    }
@@ -4860,7 +4873,11 @@ subst_reg_equivs (ad, insn)
 	    if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
 	      {
 		subst_reg_equivs_changed = 1;
-		emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+		/* We mark the USE with QImode so that we recognize it
+		   as one that can be safely deleted at the end of
+		   reload.  */
+		PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn),
+			  QImode);
 		return mem;
 	      }
 	  }
@@ -5687,7 +5704,12 @@ find_reloads_subreg_address (x, force_re
 		 this substitution.  We have to emit a USE of the pseudo so
 		 that delete_output_reload can see it.  */
 	      if (replace_reloads && recog_data.operand[opnum] != x)
-		emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
+		/* We mark the USE with QImode so that we recognize it
+		   as one that can be safely deleted at the end of
+		   reload.  */
+		PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode,
+							 SUBREG_REG (x)),
+					    insn), QImode);
 	      x = tem;
 	    }
 	}
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.255.4.11
diff -u -p -r1.255.4.11 reload1.c
--- gcc/reload1.c 2001/06/06 03:31:21 1.255.4.11
+++ gcc/reload1.c 2001/09/29 19:17:50
@@ -760,6 +760,13 @@ reload (first, global)
     {
       rtx set = single_set (insn);
 
+      /* We may introduce USEs that we want to remove at the end, so
+	 we'll mark them with QImode.  Make sure there are no
+	 previously-marked insns left by say regmove.  */
+      if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
+	  && GET_MODE (insn) != VOIDmode)
+	PUT_MODE (insn, VOIDmode);
+
       if (GET_CODE (insn) == NOTE && CONST_CALL_P (insn)
 	  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
 	for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -1187,7 +1194,9 @@ reload (first, global)
 					 CALL_INSN_FUNCTION_USAGE (insn));
 
 	if ((GET_CODE (PATTERN (insn)) == USE
-	     && find_reg_note (insn, REG_EQUAL, NULL_RTX))
+	     /* We mark with QImode USEs introduced by reload itself.  */
+	     && (GET_MODE (insn) == QImode
+		 || find_reg_note (insn, REG_EQUAL, NULL_RTX)))
 	    || (GET_CODE (PATTERN (insn)) == CLOBBER
 		&& (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
 		    || ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
@@ -8968,7 +8977,12 @@ reload_combine_note_use (xp, insn)
 
     case CLOBBER:
       if (GET_CODE (SET_DEST (x)) == REG)
-	return;
+	{
+	  /* No spurious CLOBBERs of pseudo registers may remain.  */
+	  if (REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
+	    abort ();
+	  return;
+	}
       break;
 
     case PLUS:
@@ -8985,10 +8999,9 @@ reload_combine_note_use (xp, insn)
 	int use_index;
 	int nregs;
 
-	/* Some spurious USEs of pseudo registers might remain.
-	   Just ignore them.  */
+	/* No spurious USEs of pseudo registers may remain.  */
 	if (regno >= FIRST_PSEUDO_REGISTER)
-	  return;
+	  abort ();
 
 	nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
 
Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* reload.c (find_reloads): Mark new USE insns with QImode.
	(find_reloads_toplev, find_reloads_address, subst_reg_equivs,
	find_reloads_subreg_address): Likewise.
	* regrename.c (note_sets, clear_dead_regs): Abort if pseudos are
	encountered.
	* reload1.c (reload_combine_note_use): Likewise, inside USEs and
	CLOBBERs.
	(reload): Make sure there are no USEs with mode other than
	VOIDmode.  At the end, remove those marked with QImode.

Index: gcc/regrename.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/regrename.c,v
retrieving revision 1.24
diff -u -p -r1.24 regrename.c
--- gcc/regrename.c 2001/08/22 14:35:33 1.24
+++ gcc/regrename.c 2001/09/29 19:17:45
@@ -112,6 +112,11 @@ note_sets (x, set, data)
     return;
   regno = REGNO (x);
   nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+  /* There must not be pseudos at this point.  */
+  if (regno + nregs > FIRST_PSEUDO_REGISTER)
+    abort ();
+
   while (nregs-- > 0)
     SET_HARD_REG_BIT (*pset, regno + nregs);
 }
@@ -132,6 +137,11 @@ clear_dead_regs (pset, kind, notes)
 	rtx reg = XEXP (note, 0);
 	unsigned int regno = REGNO (reg);
 	int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+
+	/* There must not be pseudos at this point.  */
+	if (regno + nregs > FIRST_PSEUDO_REGISTER)
+	  abort ();
+
 	while (nregs-- > 0)
 	  CLEAR_HARD_REG_BIT (*pset, regno + nregs);
       }
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.163
diff -u -p -r1.163 reload.c
--- gcc/reload.c 2001/09/21 21:06:18 1.163
+++ gcc/reload.c 2001/09/29 19:17:45
@@ -3816,7 +3816,11 @@ find_reloads (insn, replace, ind_levels,
 	    if (GET_CODE (operand) == REG)
 	      {
 		if (modified[i] != RELOAD_WRITE)
-		  emit_insn_before (gen_rtx_USE (VOIDmode, operand), insn);
+		  /* We mark the USE with QImode so that we recognize
+		     it as one that can be safely deleted at the end
+		     of reload.  */
+		  PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, operand),
+					      insn), QImode);
 		if (modified[i] != RELOAD_READ)
 		  emit_insn_after (gen_rtx_CLOBBER (VOIDmode, operand), insn);
 	      }
@@ -4302,7 +4306,11 @@ find_reloads_toplev (x, opnum, type, ind
 		 this substitution.  We have to emit a USE of the pseudo so
 		 that delete_output_reload can see it.  */
 	      if (replace_reloads && recog_data.operand[opnum] != x)
-		emit_insn_before (gen_rtx_USE (VOIDmode, x), insn);
+		/* We mark the USE with QImode so that we recognize it
+		   as one that can be safely deleted at the end of
+		   reload.  */
+		PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn),
+			  QImode);
 	      x = mem;
 	      i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
 					opnum, type, ind_levels, insn);
@@ -4561,7 +4569,12 @@ find_reloads_address (mode, memrefloc, a
 		      && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
 		    {
 		      *loc = tem;
-		      emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+		      /* We mark the USE with QImode so that we
+			 recognize it as one that can be safely
+			 deleted at the end of reload.  */
+		      PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, ad),
+						  insn), QImode);
+
 		      /* This doesn't really count as replacing the address
 			 as a whole, since it is still a memory access.  */
 		    }
@@ -4892,7 +4905,11 @@ subst_reg_equivs (ad, insn)
 	    if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
 	      {
 		subst_reg_equivs_changed = 1;
-		emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+		/* We mark the USE with QImode so that we recognize it
+		   as one that can be safely deleted at the end of
+		   reload.  */
+		PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn),
+			  QImode);
 		return mem;
 	      }
 	  }
@@ -5724,7 +5741,12 @@ find_reloads_subreg_address (x, force_re
 		 this substitution.  We have to emit a USE of the pseudo so
 		 that delete_output_reload can see it.  */
 	      if (replace_reloads && recog_data.operand[opnum] != x)
-		emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
+		/* We mark the USE with QImode so that we recognize it
+		   as one that can be safely deleted at the end of
+		   reload.  */
+		PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode,
+							 SUBREG_REG (x)),
+					    insn), QImode);
 	      x = tem;
 	    }
 	}
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.296
diff -u -p -r1.296 reload1.c
--- gcc/reload1.c 2001/09/25 15:26:54 1.296
+++ gcc/reload1.c 2001/09/29 19:17:46
@@ -758,6 +758,13 @@ reload (first, global)
     {
       rtx set = single_set (insn);
 
+      /* We may introduce USEs that we want to remove at the end, so
+	 we'll mark them with QImode.  Make sure there are no
+	 previously-marked insns left by say regmove.  */
+      if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
+	  && GET_MODE (insn) != VOIDmode)
+	PUT_MODE (insn, VOIDmode);
+
       if (GET_CODE (insn) == CALL_INSN
 	  && find_reg_note (insn, REG_SETJMP, NULL))
 	for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -1183,7 +1190,9 @@ reload (first, global)
 					 CALL_INSN_FUNCTION_USAGE (insn));
 
 	if ((GET_CODE (PATTERN (insn)) == USE
-	     && find_reg_note (insn, REG_EQUAL, NULL_RTX))
+	     /* We mark with QImode USEs introduced by reload itself.  */
+	     && (GET_MODE (insn) == QImode
+		 || find_reg_note (insn, REG_EQUAL, NULL_RTX)))
 	    || (GET_CODE (PATTERN (insn)) == CLOBBER
 		&& (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
 		    || ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
@@ -8929,7 +8938,12 @@ reload_combine_note_use (xp, insn)
 
     case CLOBBER:
       if (GET_CODE (SET_DEST (x)) == REG)
-	return;
+	{
+	  /* No spurious CLOBBERs of pseudo registers may remain.  */
+	  if (REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
+	    abort ();
+	  return;
+	}
       break;
 
     case PLUS:
@@ -8946,10 +8960,9 @@ reload_combine_note_use (xp, insn)
 	int use_index;
 	int nregs;
 
-	/* Some spurious USEs of pseudo registers might remain.
-	   Just ignore them.  */
+	/* No spurious USEs of pseudo registers may remain.  */
 	if (regno >= FIRST_PSEUDO_REGISTER)
-	  return;
+	  abort ();
 
 	nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
 

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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