From bd15e32c71b65cf399dfe72708b8ab3f35550dfe Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 2 Aug 2011 00:35:24 +0930 Subject: [PATCH] linux-unwind.h (frob_update_context <__powerpc64__>): Restore for indirect call bcrtl from correct stack slot... 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 | 14 +++++++-- gcc/config/rs6000/rs6000-protos.h | 2 -- gcc/config/rs6000/rs6000.c | 46 ++++++++++++++++++----------- libgcc/ChangeLog | 6 ++++ libgcc/config/rs6000/linux-unwind.h | 18 ++++++----- 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1551038cd2..2556c3a9f61 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ +2011-08-02 Alan Modra + + * 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 - + * config/avr/avr-devices.c: Delete SVN property svn:executable. * config/avr/predicates.md: Ditto. * config/avr/driver-avr.c: Ditto. @@ -137,7 +147,7 @@ (loop_carried_phi): Likewise. (propagate_rank): Likewise. (get_rank): Add calls to phi_rank and propagate_rank. - + 2011-07-31 H.J. Lu * config/i386/x86-64.h (SIZE_TYPE): Check TARGET_LP64 instead diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 357f7e72005..73da0f69f47 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -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 */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index fa367fea54c..dcf78567068 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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); diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 9108e46c9f0..1685c9fa7c3 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,9 @@ +2011-08-02 Alan Modra + + * 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 * config.host (arm*-*-linux*, arm*-*-uclinux*, arm*-*-eabi*) diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h index 48009251fbc..20116326c3c 100644 --- a/libgcc/config/rs6000/linux-unwind.h +++ b/libgcc/config/rs6000/linux-unwind.h @@ -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 -- 2.30.2