Patchwork [alpha] : Prevent another case of linker issues with exception handler

login
register
mail settings
Submitter Uros Bizjak
Date Aug. 9, 2012, 1:06 p.m.
Message ID <CAFULd4ayXHKsiairWP5zdLE-TMuVcOYR_Htd9fsMsQcamD898g@mail.gmail.com>
Download mbox | patch
Permalink /patch/176080/
State New
Headers show

Comments

Uros Bizjak - Aug. 9, 2012, 1:06 p.m.
On Thu, Aug 9, 2012 at 3:04 PM, Uros Bizjak <ubizjak@gmail.com> wrote:

> 2012-08-09  Uros Bizjak  <ubizjak@gmail.com>
>
>         * config/alpha/alpha.c (alpha_pad_noreturn): Rename to ...
>         (alpha_pad_function_end): ... this.  Also insert NOP between
>         sibling call and GP load.
>         (alpha_reorg): Update call to alpha_pad_function_end.  Expand comment.
>
> Patch was bootstrapped and regression tested on alphaev68-pc-linux-gnu.
>
> OK for mainline and release branches?

Now with the patch.

Uros.

Patch

Index: alpha.c
===================================================================
--- alpha.c	(revision 190247)
+++ alpha.c	(working copy)
@@ -9258,17 +9258,18 @@  alpha_align_insns (unsigned int max_align,
     }
 }
 
-/* Insert an unop between a noreturn function call and GP load.  */
+/* Insert an unop between sibcall or noreturn function call and GP load.  */
 
 static void
-alpha_pad_noreturn (void)
+alpha_pad_function_end (void)
 {
   rtx insn, next;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
       if (! (CALL_P (insn)
-	     && find_reg_note (insn, REG_NORETURN, NULL_RTX)))
+	     && (SIBLING_CALL_P (insn)
+		 || find_reg_note (insn, REG_NORETURN, NULL_RTX))))
         continue;
 
       /* Make sure we do not split a call and its corresponding
@@ -9300,11 +9301,31 @@  static void
 static void
 alpha_reorg (void)
 {
-  /* Workaround for a linker error that triggers when an
-     exception handler immediatelly follows a noreturn function.
+  /* Workaround for a linker error that triggers when an exception
+     handler immediatelly follows a sibcall or a noreturn function.
 
+In the sibcall case:
+
      The instruction stream from an object file:
 
+ 1d8:   00 00 fb 6b     jmp     (t12)
+ 1dc:   00 00 ba 27     ldah    gp,0(ra)
+ 1e0:   00 00 bd 23     lda     gp,0(gp)
+ 1e4:   00 00 7d a7     ldq     t12,0(gp)
+ 1e8:   00 40 5b 6b     jsr     ra,(t12),1ec <__funcZ+0x1ec>
+
+     was converted in the final link pass to:
+
+   12003aa88:   67 fa ff c3     br      120039428 <...>
+   12003aa8c:   00 00 fe 2f     unop
+   12003aa90:   00 00 fe 2f     unop
+   12003aa94:   48 83 7d a7     ldq     t12,-31928(gp)
+   12003aa98:   00 40 5b 6b     jsr     ra,(t12),12003aa9c <__func+0x1ec>
+
+And in the noreturn case:
+
+     The instruction stream from an object file:
+
   54:   00 40 5b 6b     jsr     ra,(t12),58 <__func+0x58>
   58:   00 00 ba 27     ldah    gp,0(ra)
   5c:   00 00 bd 23     lda     gp,0(gp)
@@ -9321,11 +9342,11 @@  alpha_reorg (void)
 
      GP load instructions were wrongly cleared by the linker relaxation
      pass.  This workaround prevents removal of GP loads by inserting
-     an unop instruction between a noreturn function call and
+     an unop instruction between a sibcall or noreturn function call and
      exception handler prologue.  */
 
   if (current_function_has_exception_handlers ())
-    alpha_pad_noreturn ();
+    alpha_pad_function_end ();
 
   if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
     alpha_handle_trap_shadows ();