From: Richard Henderson Date: Tue, 5 Jul 2011 17:03:41 +0000 (-0700) Subject: arm: Use REG_CFA_REGISTER instead of UNSPEC_STACK_ALIGN. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ddc6e7d62c53eb1ef02410d5494bd3fd726b9f68;p=gcc.git arm: Use REG_CFA_REGISTER instead of UNSPEC_STACK_ALIGN. This requires a bit of extra preparation in arm_unwind_emit, in order to handle the change for ARM unwinding. * config/arm/arm.c (arm_dwarf_handle_frame_unspec): Remove. (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Remove. (arm_expand_prologue): Use REG_CFA_REGISTER to mark the stack pointer save. (arm_unwind_emit_set): Don't recognize UNSPEC_STACK_ALIGN. (arm_unwind_emit): Walk REG_NOTES for unwinding notes. Emit proper unwind info for a REG_CFA_REGISTER save of stack pointer. * config/arm/arm.md (UNSPEC_STACK_ALIGN): Remove. From-SVN: r175870 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4b3438a51f5..31ca36d1784 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2011-07-05 Richard Henderson + + * config/arm/arm.c (arm_dwarf_handle_frame_unspec): Remove. + (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Remove. + (arm_expand_prologue): Use REG_CFA_REGISTER to mark the + stack pointer save. + (arm_unwind_emit_set): Don't recognize UNSPEC_STACK_ALIGN. + (arm_unwind_emit): Walk REG_NOTES for unwinding notes. Emit + proper unwind info for a REG_CFA_REGISTER save of stack pointer. + * config/arm/arm.md (UNSPEC_STACK_ALIGN): Remove. + 2011-07-05 Richard Henderson * config/vax/vax.md (define_c_enum unspecv): New. Define the diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 4c6041ab553..0e371f30167 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -203,7 +203,6 @@ static bool arm_output_ttype (rtx); static void arm_asm_emit_except_personality (rtx); static void arm_asm_init_sections (void); #endif -static void arm_dwarf_handle_frame_unspec (const char *, rtx, int); static rtx arm_dwarf_register_span (rtx); static tree arm_cxx_guard_type (void); @@ -501,9 +500,6 @@ static const struct attribute_spec arm_attribute_table[] = #define TARGET_ASM_INIT_SECTIONS arm_asm_init_sections #endif /* ARM_UNWIND_INFO */ -#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC -#define TARGET_DWARF_HANDLE_FRAME_UNSPEC arm_dwarf_handle_frame_unspec - #undef TARGET_DWARF_REGISTER_SPAN #define TARGET_DWARF_REGISTER_SPAN arm_dwarf_register_span @@ -15830,9 +15826,8 @@ arm_expand_prologue (void) if (IS_STACKALIGN (func_type)) { - rtx dwarf; - rtx r0; - rtx r1; + rtx r0, r1; + /* Handle a word-aligned stack pointer. We generate the following: mov r0, sp @@ -15848,15 +15843,18 @@ arm_expand_prologue (void) r0 = gen_rtx_REG (SImode, 0); r1 = gen_rtx_REG (SImode, 1); - /* Use a real rtvec rather than NULL_RTVEC so the rest of the - compiler won't choke. */ - dwarf = gen_rtx_UNSPEC (SImode, rtvec_alloc (0), UNSPEC_STACK_ALIGN); - dwarf = gen_rtx_SET (VOIDmode, r0, dwarf); - insn = gen_movsi (r0, stack_pointer_rtx); + + insn = emit_insn (gen_movsi (r0, stack_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf); - emit_insn (insn); + add_reg_note (insn, REG_CFA_REGISTER, NULL); + emit_insn (gen_andsi3 (r1, r0, GEN_INT (~(HOST_WIDE_INT)7))); + + /* ??? The CFA changes here, which may cause GDB to conclude that it + has entered a different function. That said, the unwind info is + correct, individually, before and after this instruction because + we've described the save of SP, which will override the default + handling of SP as restoring from the CFA. */ emit_insn (gen_movsi (stack_pointer_rtx, r1)); } @@ -22880,13 +22878,6 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) asm_fprintf (asm_out_file, "\t.movsp %r, #%d\n", REGNO (e0), (int)INTVAL(XEXP (e1, 1))); } - else if (GET_CODE (e1) == UNSPEC && XINT (e1, 1) == UNSPEC_STACK_ALIGN) - { - /* Stack pointer save before alignment. */ - reg = REGNO (e0); - asm_fprintf (asm_out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n", - reg + 0x90, reg); - } else abort (); break; @@ -22902,7 +22893,8 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) static void arm_unwind_emit (FILE * asm_out_file, rtx insn) { - rtx pat; + rtx note, pat; + bool handled_one = false; if (arm_except_unwind_info (&global_options) != UI_TARGET) return; @@ -22912,14 +22904,56 @@ arm_unwind_emit (FILE * asm_out_file, rtx insn) || crtl->all_throwers_are_sibcalls)) return; - if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn)) + if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn)) return; - pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); - if (pat) - pat = XEXP (pat, 0); - else - pat = PATTERN (insn); + for (note = REG_NOTES (insn); note ; note = XEXP (note, 1)) + { + pat = XEXP (note, 0); + switch (REG_NOTE_KIND (note)) + { + case REG_FRAME_RELATED_EXPR: + goto found; + + case REG_CFA_REGISTER: + if (pat == NULL) + { + pat = PATTERN (insn); + if (GET_CODE (pat) == PARALLEL) + pat = XVECEXP (pat, 0, 0); + } + + /* Only emitted for IS_STACKALIGN re-alignment. */ + { + rtx dest, src; + unsigned reg; + + src = SET_SRC (pat); + dest = SET_DEST (pat); + + gcc_assert (src == stack_pointer_rtx); + reg = REGNO (dest); + asm_fprintf (asm_out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n", + reg + 0x90, reg); + } + handled_one = true; + break; + + case REG_CFA_DEF_CFA: + case REG_CFA_EXPRESSION: + case REG_CFA_ADJUST_CFA: + case REG_CFA_OFFSET: + /* ??? Only handling here what we actually emit. */ + gcc_unreachable (); + + default: + break; + } + } + if (handled_one) + return; + pat = PATTERN (insn); + found: switch (GET_CODE (pat)) { @@ -22975,30 +23009,6 @@ arm_asm_init_sections (void) } #endif /* ARM_UNWIND_INFO */ -/* Handle UNSPEC DWARF call frame instructions. These are needed for dynamic - stack alignment. */ - -static void -arm_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index) -{ - rtx unspec = SET_SRC (pattern); - gcc_assert (GET_CODE (unspec) == UNSPEC); - - switch (index) - { - case UNSPEC_STACK_ALIGN: - /* ??? We should set the CFA = (SP & ~7). At this point we haven't - put anything on the stack, so hopefully it won't matter. - CFA = SP will be correct after alignment. */ - dwarf2out_reg_save_reg (label, stack_pointer_rtx, - SET_DEST (pattern)); - break; - default: - gcc_unreachable (); - } -} - - /* Output unwind directives for the start/end of a function. */ void diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2bf3551a414..03ae72defa3 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -94,8 +94,6 @@ UNSPEC_TLS ; A symbol that has been treated properly for TLS usage. UNSPEC_PIC_LABEL ; A label used for PIC access that does not appear in the ; instruction stream. - UNSPEC_STACK_ALIGN ; Doubleword aligned stack pointer. Used to - ; generate correct unwind information. UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated ; correctly for PIC usage. UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a