Commit 5c255b57 by Richard Henderson Committed by Richard Henderson

ia64.c (ia64_dwarf_handle_frame_unspec): New.

        * config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): New.
        (TARGET_DWARF_HANDLE_FRAME_UNSPEC): New.
        (do_spill): Use REG_CFA_OFFSET.
        (ia64_expand_prologue): Use REG_CFA_ADJUST_CFA and REG_CFA_REGISTER
        as appropriate.
        (ia64_expand_epilogue): Likewise.
        (process_set): Split into ...
        (process_cfa_adjust_cfa): this,
        (process_cfa_register): this,
        (process_cfa_offset): and this new function.
        (ia64_asm_unwind_emit): Use them.  Expect REG_CFA_* notes
        instead of REG_FRAME_RELATED_EXPR.

From-SVN: r164609
parent 42d87712
2010-09-24 Richard Henderson <rth@redhat.com>
* config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): New.
(TARGET_DWARF_HANDLE_FRAME_UNSPEC): New.
(do_spill): Use REG_CFA_OFFSET.
(ia64_expand_prologue): Use REG_CFA_ADJUST_CFA and REG_CFA_REGISTER
as appropriate.
(ia64_expand_epilogue): Likewise.
(process_set): Split into ...
(process_cfa_adjust_cfa): this,
(process_cfa_register): this,
(process_cfa_offset): and this new function.
(ia64_asm_unwind_emit): Use them. Expect REG_CFA_* notes
instead of REG_FRAME_RELATED_EXPR.
2010-09-24 Olivier Hainque <hainque@adacore.com> 2010-09-24 Olivier Hainque <hainque@adacore.com>
* config/i386/vx-common.h (DBX_REGISTER_NUMBER): Reinstate. * config/i386/vx-common.h (DBX_REGISTER_NUMBER): Reinstate.
...@@ -230,7 +230,6 @@ static void emit_predicate_relation_info (void); ...@@ -230,7 +230,6 @@ static void emit_predicate_relation_info (void);
static void ia64_reorg (void); static void ia64_reorg (void);
static bool ia64_in_small_data_p (const_tree); static bool ia64_in_small_data_p (const_tree);
static void process_epilogue (FILE *, rtx, bool, bool); static void process_epilogue (FILE *, rtx, bool, bool);
static int process_set (FILE *, rtx, rtx, bool, bool);
static bool ia64_assemble_integer (rtx, unsigned int, int); static bool ia64_assemble_integer (rtx, unsigned int, int);
static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT); static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
...@@ -318,6 +317,8 @@ static enum machine_mode ia64_promote_function_mode (const_tree, ...@@ -318,6 +317,8 @@ static enum machine_mode ia64_promote_function_mode (const_tree,
int); int);
static void ia64_trampoline_init (rtx, tree, rtx); static void ia64_trampoline_init (rtx, tree, rtx);
static void ia64_override_options_after_change (void); static void ia64_override_options_after_change (void);
static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int);
/* Table of valid machine attributes. */ /* Table of valid machine attributes. */
static const struct attribute_spec ia64_attribute_table[] = static const struct attribute_spec ia64_attribute_table[] =
...@@ -527,6 +528,8 @@ static const struct attribute_spec ia64_attribute_table[] = ...@@ -527,6 +528,8 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_GIMPLIFY_VA_ARG_EXPR #undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ia64_dwarf_handle_frame_unspec
#undef TARGET_ASM_UNWIND_EMIT #undef TARGET_ASM_UNWIND_EMIT
#define TARGET_ASM_UNWIND_EMIT ia64_asm_unwind_emit #define TARGET_ASM_UNWIND_EMIT ia64_asm_unwind_emit
#undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY #undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
...@@ -3035,7 +3038,7 @@ do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off, ...@@ -3035,7 +3038,7 @@ do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off,
off = current_frame_info.total_size - cfa_off; off = current_frame_info.total_size - cfa_off;
} }
add_reg_note (insn, REG_FRAME_RELATED_EXPR, add_reg_note (insn, REG_CFA_OFFSET,
gen_rtx_SET (VOIDmode, gen_rtx_SET (VOIDmode,
gen_rtx_MEM (GET_MODE (reg), gen_rtx_MEM (GET_MODE (reg),
plus_constant (base, off)), plus_constant (base, off)),
...@@ -3219,6 +3222,10 @@ ia64_expand_prologue (void) ...@@ -3219,6 +3222,10 @@ ia64_expand_prologue (void)
{ {
insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
/* Force the unwind info to recognize this as defining a new CFA,
rather than some temp register setup. */
add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL_RTX);
} }
if (current_frame_info.total_size != 0) if (current_frame_info.total_size != 0)
...@@ -3241,13 +3248,12 @@ ia64_expand_prologue (void) ...@@ -3241,13 +3248,12 @@ ia64_expand_prologue (void)
if (! frame_pointer_needed) if (! frame_pointer_needed)
{ {
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
if (GET_CODE (offset) != CONST_INT) add_reg_note (insn, REG_CFA_ADJUST_CFA,
add_reg_note (insn, REG_FRAME_RELATED_EXPR, gen_rtx_SET (VOIDmode,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
stack_pointer_rtx, gen_rtx_PLUS (DImode,
gen_rtx_PLUS (DImode, stack_pointer_rtx,
stack_pointer_rtx, frame_size_rtx)));
frame_size_rtx)));
} }
/* ??? At this point we must generate a magic insn that appears to /* ??? At this point we must generate a magic insn that appears to
...@@ -3275,7 +3281,11 @@ ia64_expand_prologue (void) ...@@ -3275,7 +3281,11 @@ ia64_expand_prologue (void)
reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM); reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
insn = emit_move_insn (ar_unat_save_reg, reg); insn = emit_move_insn (ar_unat_save_reg, reg);
RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_unat] != 0); if (current_frame_info.r[reg_save_ar_unat])
{
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
}
/* Even if we're not going to generate an epilogue, we still /* Even if we're not going to generate an epilogue, we still
need to save the register so that EH works. */ need to save the register so that EH works. */
...@@ -3314,8 +3324,7 @@ ia64_expand_prologue (void) ...@@ -3314,8 +3324,7 @@ ia64_expand_prologue (void)
/* ??? Denote pr spill/fill by a DImode move that modifies all /* ??? Denote pr spill/fill by a DImode move that modifies all
64 hard registers. */ 64 hard registers. */
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR, add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
gen_rtx_SET (VOIDmode, alt_reg, reg));
/* Even if we're not going to generate an epilogue, we still /* Even if we're not going to generate an epilogue, we still
need to save the register so that EH works. */ need to save the register so that EH works. */
...@@ -3361,6 +3370,7 @@ ia64_expand_prologue (void) ...@@ -3361,6 +3370,7 @@ ia64_expand_prologue (void)
reg_emitted (reg_save_ar_lc); reg_emitted (reg_save_ar_lc);
insn = emit_move_insn (alt_reg, reg); insn = emit_move_insn (alt_reg, reg);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
/* Even if we're not going to generate an epilogue, we still /* Even if we're not going to generate an epilogue, we still
need to save the register so that EH works. */ need to save the register so that EH works. */
...@@ -3387,6 +3397,7 @@ ia64_expand_prologue (void) ...@@ -3387,6 +3397,7 @@ ia64_expand_prologue (void)
reg_emitted (reg_save_b0); reg_emitted (reg_save_b0);
insn = emit_move_insn (alt_reg, reg); insn = emit_move_insn (alt_reg, reg);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
/* Even if we're not going to generate an epilogue, we still /* Even if we're not going to generate an epilogue, we still
need to save the register so that EH works. */ need to save the register so that EH works. */
...@@ -3677,6 +3688,7 @@ ia64_expand_epilogue (int sibcall_p) ...@@ -3677,6 +3688,7 @@ ia64_expand_epilogue (int sibcall_p)
{ {
insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL);
} }
else if (current_frame_info.total_size) else if (current_frame_info.total_size)
{ {
...@@ -3696,13 +3708,12 @@ ia64_expand_epilogue (int sibcall_p) ...@@ -3696,13 +3708,12 @@ ia64_expand_epilogue (int sibcall_p)
offset)); offset));
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
if (GET_CODE (offset) != CONST_INT) add_reg_note (insn, REG_CFA_ADJUST_CFA,
add_reg_note (insn, REG_FRAME_RELATED_EXPR, gen_rtx_SET (VOIDmode,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
stack_pointer_rtx, gen_rtx_PLUS (DImode,
gen_rtx_PLUS (DImode, stack_pointer_rtx,
stack_pointer_rtx, frame_size_rtx)));
frame_size_rtx)));
} }
if (cfun->machine->ia64_eh_epilogue_bsp) if (cfun->machine->ia64_eh_epilogue_bsp)
...@@ -3713,11 +3724,12 @@ ia64_expand_epilogue (int sibcall_p) ...@@ -3713,11 +3724,12 @@ ia64_expand_epilogue (int sibcall_p)
else else
{ {
int fp = GR_REG (2); int fp = GR_REG (2);
/* We need a throw away register here, r0 and r1 are reserved, so r2 is the /* We need a throw away register here, r0 and r1 are reserved,
first available call clobbered register. If there was a frame_pointer so r2 is the first available call clobbered register. If
register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM, there was a frame_pointer register, we may have swapped the
so we have to make sure we're using the string "r2" when emitting names of r2 and HARD_FRAME_POINTER_REGNUM, so we have to make
the register name for the assembler. */ sure we're using the string "r2" when emitting the register
name for the assembler. */
if (current_frame_info.r[reg_fp] if (current_frame_info.r[reg_fp]
&& current_frame_info.r[reg_fp] == GR_REG (2)) && current_frame_info.r[reg_fp] == GR_REG (2))
fp = HARD_FRAME_POINTER_REGNUM; fp = HARD_FRAME_POINTER_REGNUM;
...@@ -9590,6 +9602,17 @@ ia64_dwarf2out_def_steady_cfa (rtx insn, bool frame) ...@@ -9590,6 +9602,17 @@ ia64_dwarf2out_def_steady_cfa (rtx insn, bool frame)
+ ARG_POINTER_CFA_OFFSET (current_function_decl)); + ARG_POINTER_CFA_OFFSET (current_function_decl));
} }
/* All we need to do here is avoid a crash in the generic dwarf2
processing. The real CFA definition is set up above. */
static void
ia64_dwarf_handle_frame_unspec (const char * ARG_UNUSED (label),
rtx ARG_UNUSED (pattern),
int index)
{
gcc_assert (index == UNSPECV_ALLOC);
}
/* The generic dwarf2 frame debug info generator does not define a /* The generic dwarf2 frame debug info generator does not define a
separate region for the very end of the epilogue, so refrain from separate region for the very end of the epilogue, so refrain from
doing so in the IA64-specific code as well. */ doing so in the IA64-specific code as well. */
...@@ -9619,53 +9642,19 @@ process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame) ...@@ -9619,53 +9642,19 @@ process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame)
STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
} }
/* This function processes a SET pattern looking for specific patterns /* This function processes a SET pattern for REG_CFA_ADJUST_CFA. */
which result in emitting an assembly directive required for unwinding. */
static int static void
process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn,
bool unwind, bool frame)
{ {
rtx src = SET_SRC (pat);
rtx dest = SET_DEST (pat); rtx dest = SET_DEST (pat);
int src_regno, dest_regno; rtx src = SET_SRC (pat);
/* Look for the ALLOC insn. */
if (GET_CODE (src) == UNSPEC_VOLATILE
&& XINT (src, 1) == UNSPECV_ALLOC
&& GET_CODE (dest) == REG)
{
dest_regno = REGNO (dest);
/* If this is the final destination for ar.pfs, then this must
be the alloc in the prologue. */
if (dest_regno == current_frame_info.r[reg_save_ar_pfs])
{
if (unwind)
fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
ia64_dbx_register_number (dest_regno));
}
else
{
/* This must be an alloc before a sibcall. We must drop the
old frame info. The easiest way to drop the old frame
info is to ensure we had a ".restore sp" directive
followed by a new prologue. If the procedure doesn't
have a memory-stack frame, we'll issue a dummy ".restore
sp" now. */
if (current_frame_info.total_size == 0 && !frame_pointer_needed)
/* if haven't done process_epilogue() yet, do it now */
process_epilogue (asm_out_file, insn, unwind, frame);
if (unwind)
fprintf (asm_out_file, "\t.prologue\n");
}
return 1;
}
/* Look for SP = .... */ if (dest == stack_pointer_rtx)
if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM)
{ {
if (GET_CODE (src) == PLUS) if (GET_CODE (src) == PLUS)
{ {
rtx op0 = XEXP (src, 0); rtx op0 = XEXP (src, 0);
rtx op1 = XEXP (src, 1); rtx op1 = XEXP (src, 1);
...@@ -9675,7 +9664,8 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) ...@@ -9675,7 +9664,8 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
{ {
gcc_assert (!frame_pointer_needed); gcc_assert (!frame_pointer_needed);
if (unwind) if (unwind)
fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n", fprintf (asm_out_file,
"\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
-INTVAL (op1)); -INTVAL (op1));
ia64_dwarf2out_def_steady_cfa (insn, frame); ia64_dwarf2out_def_steady_cfa (insn, frame);
} }
...@@ -9684,240 +9674,303 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) ...@@ -9684,240 +9674,303 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
} }
else else
{ {
gcc_assert (GET_CODE (src) == REG gcc_assert (src == hard_frame_pointer_rtx);
&& REGNO (src) == HARD_FRAME_POINTER_REGNUM);
process_epilogue (asm_out_file, insn, unwind, frame); process_epilogue (asm_out_file, insn, unwind, frame);
} }
}
else if (dest == hard_frame_pointer_rtx)
{
gcc_assert (src == stack_pointer_rtx);
gcc_assert (frame_pointer_needed);
return 1; if (unwind)
fprintf (asm_out_file, "\t.vframe r%d\n",
ia64_dbx_register_number (REGNO (dest)));
ia64_dwarf2out_def_steady_cfa (insn, frame);
} }
else
gcc_unreachable ();
}
/* Register move we need to look at. */ /* This function processes a SET pattern for REG_CFA_REGISTER. */
if (GET_CODE (dest) == REG && GET_CODE (src) == REG)
{
src_regno = REGNO (src);
dest_regno = REGNO (dest);
switch (src_regno) static void
{ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind)
case BR_REG (0): {
/* Saving return address pointer. */ rtx dest = SET_DEST (pat);
gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]); rtx src = SET_SRC (pat);
if (unwind)
fprintf (asm_out_file, "\t.save rp, r%d\n",
ia64_dbx_register_number (dest_regno));
return 1;
case PR_REG (0): int dest_regno = REGNO (dest);
gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); int src_regno = REGNO (src);
if (unwind)
fprintf (asm_out_file, "\t.save pr, r%d\n",
ia64_dbx_register_number (dest_regno));
return 1;
case AR_UNAT_REGNUM: switch (src_regno)
gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); {
if (unwind) case BR_REG (0):
fprintf (asm_out_file, "\t.save ar.unat, r%d\n", /* Saving return address pointer. */
ia64_dbx_register_number (dest_regno)); gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]);
return 1; if (unwind)
fprintf (asm_out_file, "\t.save rp, r%d\n",
ia64_dbx_register_number (dest_regno));
break;
case AR_LC_REGNUM: case PR_REG (0):
gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]);
if (unwind) if (unwind)
fprintf (asm_out_file, "\t.save ar.lc, r%d\n", fprintf (asm_out_file, "\t.save pr, r%d\n",
ia64_dbx_register_number (dest_regno)); ia64_dbx_register_number (dest_regno));
return 1; break;
case STACK_POINTER_REGNUM: case AR_UNAT_REGNUM:
gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]);
&& frame_pointer_needed); if (unwind)
if (unwind) fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
fprintf (asm_out_file, "\t.vframe r%d\n", ia64_dbx_register_number (dest_regno));
ia64_dbx_register_number (dest_regno)); break;
ia64_dwarf2out_def_steady_cfa (insn, frame);
return 1;
default: case AR_LC_REGNUM:
/* Everything else should indicate being stored to memory. */ gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]);
gcc_unreachable (); if (unwind)
} fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
ia64_dbx_register_number (dest_regno));
break;
default:
/* Everything else should indicate being stored to memory. */
gcc_unreachable ();
} }
}
/* Memory store we need to look at. */ /* This function processes a SET pattern for REG_CFA_OFFSET. */
if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)
{
long off;
rtx base;
const char *saveop;
if (GET_CODE (XEXP (dest, 0)) == REG) static void
{ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind)
base = XEXP (dest, 0); {
off = 0; rtx dest = SET_DEST (pat);
} rtx src = SET_SRC (pat);
else int src_regno = REGNO (src);
{ const char *saveop;
gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS HOST_WIDE_INT off;
&& GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT); rtx base;
base = XEXP (XEXP (dest, 0), 0);
off = INTVAL (XEXP (XEXP (dest, 0), 1));
}
if (base == hard_frame_pointer_rtx) gcc_assert (MEM_P (dest));
{ if (GET_CODE (XEXP (dest, 0)) == REG)
saveop = ".savepsp"; {
off = - off; base = XEXP (dest, 0);
} off = 0;
else }
{ else
gcc_assert (base == stack_pointer_rtx); {
saveop = ".savesp"; gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS
} && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
base = XEXP (XEXP (dest, 0), 0);
off = INTVAL (XEXP (XEXP (dest, 0), 1));
}
src_regno = REGNO (src); if (base == hard_frame_pointer_rtx)
switch (src_regno) {
{ saveop = ".savepsp";
case BR_REG (0): off = - off;
gcc_assert (!current_frame_info.r[reg_save_b0]); }
if (unwind) else
fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off); {
return 1; gcc_assert (base == stack_pointer_rtx);
saveop = ".savesp";
}
case PR_REG (0): src_regno = REGNO (src);
gcc_assert (!current_frame_info.r[reg_save_pr]); switch (src_regno)
if (unwind) {
fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off); case BR_REG (0):
return 1; gcc_assert (!current_frame_info.r[reg_save_b0]);
if (unwind)
fprintf (asm_out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n",
saveop, off);
break;
case AR_LC_REGNUM: case PR_REG (0):
gcc_assert (!current_frame_info.r[reg_save_ar_lc]); gcc_assert (!current_frame_info.r[reg_save_pr]);
if (unwind) if (unwind)
fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off); fprintf (asm_out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n",
return 1; saveop, off);
break;
case AR_PFS_REGNUM: case AR_LC_REGNUM:
gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); gcc_assert (!current_frame_info.r[reg_save_ar_lc]);
if (unwind) if (unwind)
fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off); fprintf (asm_out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n",
return 1; saveop, off);
break;
case AR_UNAT_REGNUM: case AR_PFS_REGNUM:
gcc_assert (!current_frame_info.r[reg_save_ar_unat]); gcc_assert (!current_frame_info.r[reg_save_ar_pfs]);
if (unwind) if (unwind)
fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off); fprintf (asm_out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n",
return 1; saveop, off);
break;
case GR_REG (4): case AR_UNAT_REGNUM:
case GR_REG (5): gcc_assert (!current_frame_info.r[reg_save_ar_unat]);
case GR_REG (6): if (unwind)
case GR_REG (7): fprintf (asm_out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n",
if (unwind) saveop, off);
fprintf (asm_out_file, "\t.save.g 0x%x\n", break;
1 << (src_regno - GR_REG (4)));
return 1;
case BR_REG (1): case GR_REG (4):
case BR_REG (2): case GR_REG (5):
case BR_REG (3): case GR_REG (6):
case BR_REG (4): case GR_REG (7):
case BR_REG (5): if (unwind)
if (unwind) fprintf (asm_out_file, "\t.save.g 0x%x\n",
fprintf (asm_out_file, "\t.save.b 0x%x\n", 1 << (src_regno - GR_REG (4)));
1 << (src_regno - BR_REG (1))); break;
return 1;
case FR_REG (2): case BR_REG (1):
case FR_REG (3): case BR_REG (2):
case FR_REG (4): case BR_REG (3):
case FR_REG (5): case BR_REG (4):
if (unwind) case BR_REG (5):
fprintf (asm_out_file, "\t.save.f 0x%x\n", if (unwind)
1 << (src_regno - FR_REG (2))); fprintf (asm_out_file, "\t.save.b 0x%x\n",
return 1; 1 << (src_regno - BR_REG (1)));
break;
case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19): case FR_REG (2):
case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23): case FR_REG (3):
case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): case FR_REG (4):
case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): case FR_REG (5):
if (unwind) if (unwind)
fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", fprintf (asm_out_file, "\t.save.f 0x%x\n",
1 << (src_regno - FR_REG (12))); 1 << (src_regno - FR_REG (2)));
return 1; break;
default: case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
return 0; case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
} case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
} case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
if (unwind)
fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
1 << (src_regno - FR_REG (12)));
break;
return 0; default:
/* ??? For some reason we mark other general registers, even those
we can't represent in the unwind info. Ignore them. */
break;
}
} }
/* This function looks at a single insn and emits any directives /* This function looks at a single insn and emits any directives
required to unwind this insn. */ required to unwind this insn. */
static void static void
ia64_asm_unwind_emit (FILE *asm_out_file, rtx insn) ia64_asm_unwind_emit (FILE *asm_out_file, rtx insn)
{ {
bool unwind = (flag_unwind_tables bool unwind = (flag_unwind_tables
|| (flag_exceptions && !USING_SJLJ_EXCEPTIONS)); || (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
bool frame = dwarf2out_do_frame (); bool frame = dwarf2out_do_frame ();
rtx note, pat;
bool handled_one;
if (!unwind && !frame)
return;
if (unwind || frame) if (NOTE_INSN_BASIC_BLOCK_P (insn))
{ {
rtx pat; last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
if (NOTE_INSN_BASIC_BLOCK_P (insn)) /* Restore unwind state from immediately before the epilogue. */
if (need_copy_state)
{ {
last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR; if (unwind)
/* Restore unwind state from immediately before the epilogue. */
if (need_copy_state)
{ {
if (unwind) fprintf (asm_out_file, "\t.body\n");
{ fprintf (asm_out_file, "\t.copy_state %d\n",
fprintf (asm_out_file, "\t.body\n"); cfun->machine->state_num);
fprintf (asm_out_file, "\t.copy_state %d\n",
cfun->machine->state_num);
}
if (IA64_CHANGE_CFA_IN_EPILOGUE)
ia64_dwarf2out_def_steady_cfa (insn, frame);
need_copy_state = false;
} }
if (IA64_CHANGE_CFA_IN_EPILOGUE)
ia64_dwarf2out_def_steady_cfa (insn, frame);
need_copy_state = false;
} }
}
if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn)) if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
return; return;
/* Look for the ALLOC insn. */
if (INSN_CODE (insn) == CODE_FOR_alloc)
{
rtx dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
int dest_regno = REGNO (dest);
pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); /* If this is the final destination for ar.pfs, then this must
if (pat) be the alloc in the prologue. */
pat = XEXP (pat, 0); if (dest_regno == current_frame_info.r[reg_save_ar_pfs])
{
if (unwind)
fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
ia64_dbx_register_number (dest_regno));
}
else else
pat = PATTERN (insn); {
/* This must be an alloc before a sibcall. We must drop the
old frame info. The easiest way to drop the old frame
info is to ensure we had a ".restore sp" directive
followed by a new prologue. If the procedure doesn't
have a memory-stack frame, we'll issue a dummy ".restore
sp" now. */
if (current_frame_info.total_size == 0 && !frame_pointer_needed)
/* if haven't done process_epilogue() yet, do it now */
process_epilogue (asm_out_file, insn, unwind, frame);
if (unwind)
fprintf (asm_out_file, "\t.prologue\n");
}
return;
}
switch (GET_CODE (pat)) handled_one = false;
{ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
case SET: switch (REG_NOTE_KIND (note))
process_set (asm_out_file, pat, insn, unwind, frame); {
break; case REG_CFA_ADJUST_CFA:
pat = XEXP (note, 0);
if (pat == NULL)
pat = PATTERN (insn);
process_cfa_adjust_cfa (asm_out_file, pat, insn, unwind, frame);
handled_one = true;
break;
case PARALLEL: case REG_CFA_OFFSET:
{ pat = XEXP (note, 0);
int par_index; if (pat == NULL)
int limit = XVECLEN (pat, 0); pat = PATTERN (insn);
for (par_index = 0; par_index < limit; par_index++) process_cfa_offset (asm_out_file, pat, unwind);
{ handled_one = true;
rtx x = XVECEXP (pat, 0, par_index); break;
if (GET_CODE (x) == SET)
process_set (asm_out_file, x, insn, unwind, frame);
}
break;
}
default: case REG_CFA_REGISTER:
gcc_unreachable (); pat = XEXP (note, 0);
} if (pat == NULL)
} pat = PATTERN (insn);
process_cfa_register (asm_out_file, pat, unwind);
handled_one = true;
break;
case REG_FRAME_RELATED_EXPR:
case REG_CFA_DEF_CFA:
case REG_CFA_EXPRESSION:
case REG_CFA_RESTORE:
case REG_CFA_SET_VDRAP:
/* Not used in the ia64 port. */
gcc_unreachable ();
default:
/* Not a frame-related note. */
break;
}
/* All REG_FRAME_RELATED_P insns, besides ALLOC, are marked with the
explicit action to take. No guessing required. */
gcc_assert (handled_one);
} }
/* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY. */ /* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment