diff mbox

[SH] PR52667, Fix for barrier insertion

Message ID 4F715FEF.4070809@codesourcery.com
State New
Headers show

Commit Message

Chung-Lin Tang March 27, 2012, 6:36 a.m. UTC
Hi Kaz,

This patch fixes a case in sh.c:find_barrier(), triggered by a testcase
in glibc. The scanning starts from a GOT move instruction, records
itself in 'last_got', but does not find a second GOT move (to reset
last_got to NULL).

It finishes by trying to insert a new barrier in the insn stream, sees
last_got != NULL, and tries to insert at PREV_INSN(last_got), which goes
above the original start insn.

The caller, sh_reorg(), then gets the barrier scan target above the orig
insn, tries (in vain) to find it using a forward scan, and segfaults
when it goes past the insn stream...

The attached patch adds an additional equality check, plus some comment
updates. Cross-tested without regressions, is this okay for trunk?

Thanks,
Chung-Lin

2012-03-27  Chung-Lin Tang  <cltang@codesourcery.com>

	PR target/52667
	* config/sh/sh.c (find_barrier): Add equality check of last_got
	to avoid going above orig insn. Update comments.

Comments

Kaz Kojima March 27, 2012, 10:17 a.m. UTC | #1
Chung-Lin Tang <cltang@codesourcery.com> wrote:
> This patch fixes a case in sh.c:find_barrier(), triggered by a testcase
> in glibc. The scanning starts from a GOT move instruction, records
> itself in 'last_got', but does not find a second GOT move (to reset
> last_got to NULL).
> 
> It finishes by trying to insert a new barrier in the insn stream, sees
> last_got != NULL, and tries to insert at PREV_INSN(last_got), which goes
> above the original start insn.
> 
> The caller, sh_reorg(), then gets the barrier scan target above the orig
> insn, tries (in vain) to find it using a forward scan, and segfaults
> when it goes past the insn stream...
> 
> The attached patch adds an additional equality check, plus some comment
> updates. Cross-tested without regressions, is this okay for trunk?

OK.  Thanks for catching this!

Regards,
	kaz
diff mbox

Patch

Index: config/sh/sh.c
===================================================================
--- config/sh/sh.c	(revision 185837)
+++ config/sh/sh.c	(working copy)
@@ -4751,8 +4751,12 @@  find_barrier (int num_mova, rtx mova, rtx from)
       /* Don't emit a constant table int the middle of global pointer setting,
 	 since that that would move the addressing base GOT into another table. 
 	 We need the first mov instruction before the _GLOBAL_OFFSET_TABLE_
-	 in the pool anyway, so just move up the whole constant pool.  */
-      if (last_got)
+	 in the pool anyway, so just move up the whole constant pool.
+
+	 However, avoid doing so when the last single GOT mov is the starting
+	 insn itself. Going past above the start insn would create a negative
+	 offset, causing errors.  */
+      if (last_got && last_got != orig)
         from = PREV_INSN (last_got);
 
       /* Don't insert the constant pool table at the position which