aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2011-07-05 10:03:41 -0700
committerRichard Henderson <rth@gcc.gnu.org>2011-07-05 10:03:41 -0700
commitddc6e7d62c53eb1ef02410d5494bd3fd726b9f68 (patch)
tree69416bb78da1ba0cfd2424e0fa6865c87fed54b8
parenta35156057510d1933a0dab5d8bd2837bfd28fa8c (diff)
downloadgcc-ddc6e7d62c53eb1ef02410d5494bd3fd726b9f68.zip
gcc-ddc6e7d62c53eb1ef02410d5494bd3fd726b9f68.tar.gz
gcc-ddc6e7d62c53eb1ef02410d5494bd3fd726b9f68.tar.bz2
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
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/arm/arm.c114
-rw-r--r--gcc/config/arm/arm.md2
3 files changed, 73 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4b3438a..31ca36d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
2011-07-05 Richard Henderson <rth@redhat.com>
+ * 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 <rth@redhat.com>
+
* config/vax/vax.md (define_c_enum unspecv): New. Define the
VUNSPEC_* constants here instead of via define_constants.
(VUNSPEC_PEM): New constant.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 4c6041a..0e371f3 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 2bf3551..03ae72d 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