linux-unwind.h (frob_update_context <__powerpc64__>): Restore for indirect call bcrtl...
authorAlan Modra <amodra@gmail.com>
Mon, 1 Aug 2011 15:05:24 +0000 (00:35 +0930)
committerAlan Modra <amodra@gcc.gnu.org>
Mon, 1 Aug 2011 15:05:24 +0000 (00:35 +0930)
libgcc/
* config/rs6000/linux-unwind.h (frob_update_context <__powerpc64__>):
Restore for indirect call bcrtl from correct stack slot, and only
if cfa+40 isn't valid.
gcc/
* config/rs6000/rs6000-protos.h (rs6000_save_toc_in_prologue_p): Delete.
* config/rs6000/rs6000.c (rs6000_save_toc_in_prologue_p): Make static.
(rs6000_emit_prologue): Don't prematurely return when
TARGET_SINGLE_PIC_BASE.  Don't emit eh_frame info in
save_toc_in_prologue case.
(rs6000_call_indirect_aix): Only disallow save_toc_in_prologue for
calls_alloca.

From-SVN: r177041

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
libgcc/ChangeLog
libgcc/config/rs6000/linux-unwind.h

index d1551038cd226dde301e518c7628993b89bc5479..2556c3a9f61664285aae6510149a8c026154d95d 100644 (file)
@@ -1,5 +1,15 @@
+2011-08-02  Alan Modra  <amodra@gmail.com>
+
+       * config/rs6000/rs6000-protos.h (rs6000_save_toc_in_prologue_p): Delete.
+       * config/rs6000/rs6000.c (rs6000_save_toc_in_prologue_p): Make static.
+       (rs6000_emit_prologue): Don't prematurely return when
+       TARGET_SINGLE_PIC_BASE.  Don't emit eh_frame info in
+       save_toc_in_prologue case.
+       (rs6000_call_indirect_aix): Only disallow save_toc_in_prologue for
+       calls_alloca.
+
 2011-08-01  Georg-Johann Lay  <avr@gjlay.de>
-       
+
        * config/avr/avr-devices.c: Delete SVN property svn:executable.
        * config/avr/predicates.md: Ditto.
        * config/avr/driver-avr.c: Ditto.
        (loop_carried_phi): Likewise.
        (propagate_rank): Likewise.
        (get_rank): Add calls to phi_rank and propagate_rank.
-       
+
 2011-07-31  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/i386/x86-64.h (SIZE_TYPE): Check TARGET_LP64 instead
index 357f7e720051cadc80102d5e8c10a68172c057b9..73da0f69f4771e98e32abb9ec5dcfec6119853ba 100644 (file)
@@ -172,8 +172,6 @@ extern void rs6000_emit_epilogue (int);
 extern void rs6000_emit_eh_reg_restore (rtx, rtx);
 extern const char * output_isel (rtx *);
 extern void rs6000_call_indirect_aix (rtx, rtx, rtx);
-extern bool rs6000_save_toc_in_prologue_p (void);
-
 extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
 
 /* Declare functions in rs6000-c.c */
index fa367fea54cfd363993e1c0d76ed6e1d20960745..dcf78567068bcb8df469541a7b0d23e6ad13f5b8 100644 (file)
@@ -1178,6 +1178,7 @@ static void rs6000_conditional_register_usage (void);
 static void rs6000_trampoline_init (rtx, tree, rtx);
 static bool rs6000_cannot_force_const_mem (enum machine_mode, rtx);
 static bool rs6000_legitimate_constant_p (enum machine_mode, rtx);
+static bool rs6000_save_toc_in_prologue_p (void);
 
 /* Hash table stuff for keeping track of TOC entries.  */
 
@@ -20478,14 +20479,12 @@ rs6000_emit_prologue (void)
       insn = emit_insn (generate_set_vrsave (reg, info, 0));
     }
 
-  if (TARGET_SINGLE_PIC_BASE)
-    return; /* Do not set PIC register */
-
   /* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up.  */
-  if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
-      || (DEFAULT_ABI == ABI_V4
-         && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
-         && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM)))
+  if (!TARGET_SINGLE_PIC_BASE
+      && ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
+         || (DEFAULT_ABI == ABI_V4
+             && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
+             && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))))
     {
       /* If emit_load_toc_table will use the link register, we need to save
         it.  We use R12 for this purpose because emit_load_toc_table
@@ -20513,7 +20512,8 @@ rs6000_emit_prologue (void)
     }
 
 #if TARGET_MACHO
-  if (DEFAULT_ABI == ABI_DARWIN
+  if (!TARGET_SINGLE_PIC_BASE
+      && DEFAULT_ABI == ABI_DARWIN
       && flag_pic && crtl->uses_pic_offset_table)
     {
       rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
@@ -20534,10 +20534,26 @@ rs6000_emit_prologue (void)
     }
 #endif
 
-  /* If we need to, save the TOC register after doing the stack setup.  */
+  /* If we need to, save the TOC register after doing the stack setup.
+     Do not emit eh frame info for this save.  The unwinder wants info,
+     conceptually attached to instructions in this function, about
+     register values in the caller of this function.  This R2 may have
+     already been changed from the value in the caller.
+     We don't attempt to write accurate DWARF EH frame info for R2
+     because code emitted by gcc for a (non-pointer) function call
+     doesn't save and restore R2.  Instead, R2 is managed out-of-line
+     by a linker generated plt call stub when the function resides in
+     a shared library.  This behaviour is costly to describe in DWARF,
+     both in terms of the size of DWARF info and the time taken in the
+     unwinder to interpret it.  R2 changes, apart from the
+     calls_eh_return case earlier in this function, are handled by
+     linux-unwind.h frob_update_context.  */ 
   if (rs6000_save_toc_in_prologue_p ())
-    emit_frame_save (sp_reg_rtx, sp_reg_rtx, reg_mode, TOC_REGNUM,
-                    5 * reg_size, info->total_size);
+    {
+      rtx addr = gen_rtx_PLUS (Pmode, sp_reg_rtx, GEN_INT (5 * reg_size));
+      rtx mem = gen_frame_mem (reg_mode, addr);
+      emit_move_insn (mem, gen_rtx_REG (reg_mode, TOC_REGNUM));
+    }
 }
 
 /* Write function prologue.  */
@@ -27795,10 +27811,7 @@ rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag)
 
   /* Can we optimize saving the TOC in the prologue or do we need to do it at
      every call?  */
-  if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca
-      && !cfun->calls_setjmp && !cfun->has_nonlocal_label
-      && !cfun->can_throw_non_call_exceptions
-      && ((flags_from_decl_or_type (cfun->decl) & ECF_NOTHROW) == ECF_NOTHROW))
+  if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
     cfun->machine->save_toc_in_prologue = true;
 
   else
@@ -27834,13 +27847,12 @@ rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag)
     insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem);
 
   emit_call_insn (insn);
-  return;
 }
 
 /* Return whether we need to always update the saved TOC pointer when we update
    the stack pointer.  */
 
-bool
+static bool
 rs6000_save_toc_in_prologue_p (void)
 {
   return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
index 9108e46c9f01af16f61da8a97b38642a6dbc4c87..1685c9fa7c3b6ea8736948fe46a41d6e6e68354f 100644 (file)
@@ -1,3 +1,9 @@
+2011-08-02  Alan Modra  <amodra@gmail.com>
+
+       * config/rs6000/linux-unwind.h (frob_update_context <__powerpc64__>):
+       Restore for indirect call bcrtl from correct stack slot, and only
+       if cfa+40 isn't valid.
+
 2011-08-01  Julian Brown  <julian@codesourcery.com>
 
        * config.host (arm*-*-linux*, arm*-*-uclinux*, arm*-*-eabi*)
index 48009251fbc60dca980a7ed270bd7c48c84d45bb..20116326c3c863dc8e129e73f98df7dc3b0ac606 100644 (file)
@@ -354,20 +354,22 @@ frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATT
          /* We are in a plt call stub or r2 adjusting long branch stub,
             before r2 has been saved.  Keep REG_UNSAVED.  */
        }
-      else if (pc[0] == 0x4E800421
-              && pc[1] == 0xE8410028)
-       {
-         /* We are at the bctrl instruction in a call via function
-            pointer.  gcc always emits the load of the new r2 just
-            before the bctrl.  */
-         _Unwind_SetGRPtr (context, 2, context->cfa + 40);
-       }
       else
        {
          unsigned int *insn
            = (unsigned int *) _Unwind_GetGR (context, R_LR);
          if (insn && *insn == 0xE8410028)
            _Unwind_SetGRPtr (context, 2, context->cfa + 40);
+         else if (pc[0] == 0x4E800421
+                  && pc[1] == 0xE8410028)
+           {
+             /* We are at the bctrl instruction in a call via function
+                pointer.  gcc always emits the load of the new R2 just
+                before the bctrl so this is the first and only place
+                we need to use the stored R2.  */
+             _Unwind_Word sp = _Unwind_GetGR (context, 1);
+             _Unwind_SetGRPtr (context, 2, sp + 40);
+           }
        }
     }
 #endif