Commit 652a3e3a by Jakub Jelinek Committed by Jakub Jelinek

re PR debug/59575 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2239)

	PR target/59575
	* config/arm/arm.c (emit_multi_reg_push): Add dwarf_regs_mask argument,
	don't record in REG_FRAME_RELATED_EXPR registers not set in that
	bitmask.
	(arm_expand_prologue): Adjust all callers.
	(arm_unwind_emit_sequence): Allow saved, but not important for unwind
	info, registers also at the lowest numbered registers side.  Use
	gcc_assert instead of abort, and SET_SRC/SET_DEST macros instead of
	XEXP.

	* gcc.target/arm/pr59575.c: New test.

From-SVN: r207563
parent af116cae
2014-02-06 Jakub Jelinek <jakub@redhat.com> 2014-02-06 Jakub Jelinek <jakub@redhat.com>
PR target/59575
* config/arm/arm.c (emit_multi_reg_push): Add dwarf_regs_mask argument,
don't record in REG_FRAME_RELATED_EXPR registers not set in that
bitmask.
(arm_expand_prologue): Adjust all callers.
(arm_unwind_emit_sequence): Allow saved, but not important for unwind
info, registers also at the lowest numbered registers side. Use
gcc_assert instead of abort, and SET_SRC/SET_DEST macros instead of
XEXP.
PR debug/59992 PR debug/59992
* var-tracking.c (adjust_mems): Before adding a SET * var-tracking.c (adjust_mems): Before adding a SET
to amd->side_effects, adjust it's SET_SRC using to amd->side_effects, adjust it's SET_SRC using
......
...@@ -177,7 +177,7 @@ static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int); ...@@ -177,7 +177,7 @@ static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
static tree arm_builtin_decl (unsigned, bool); static tree arm_builtin_decl (unsigned, bool);
static void emit_constant_insn (rtx cond, rtx pattern); static void emit_constant_insn (rtx cond, rtx pattern);
static rtx emit_set_insn (rtx, rtx); static rtx emit_set_insn (rtx, rtx);
static rtx emit_multi_reg_push (unsigned long); static rtx emit_multi_reg_push (unsigned long, unsigned long);
static int arm_arg_partial_bytes (cumulative_args_t, enum machine_mode, static int arm_arg_partial_bytes (cumulative_args_t, enum machine_mode,
tree, bool); tree, bool);
static rtx arm_function_arg (cumulative_args_t, enum machine_mode, static rtx arm_function_arg (cumulative_args_t, enum machine_mode,
...@@ -19573,28 +19573,33 @@ arm_emit_strd_push (unsigned long saved_regs_mask) ...@@ -19573,28 +19573,33 @@ arm_emit_strd_push (unsigned long saved_regs_mask)
/* Generate and emit an insn that we will recognize as a push_multi. /* Generate and emit an insn that we will recognize as a push_multi.
Unfortunately, since this insn does not reflect very well the actual Unfortunately, since this insn does not reflect very well the actual
semantics of the operation, we need to annotate the insn for the benefit semantics of the operation, we need to annotate the insn for the benefit
of DWARF2 frame unwind information. */ of DWARF2 frame unwind information. DWARF_REGS_MASK is a subset of
MASK for registers that should be annotated for DWARF2 frame unwind
information. */
static rtx static rtx
emit_multi_reg_push (unsigned long mask) emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
{ {
int num_regs = 0; int num_regs = 0;
int num_dwarf_regs; int num_dwarf_regs = 0;
int i, j; int i, j;
rtx par; rtx par;
rtx dwarf; rtx dwarf;
int dwarf_par_index; int dwarf_par_index;
rtx tmp, reg; rtx tmp, reg;
/* We don't record the PC in the dwarf frame information. */
dwarf_regs_mask &= ~(1 << PC_REGNUM);
for (i = 0; i <= LAST_ARM_REGNUM; i++) for (i = 0; i <= LAST_ARM_REGNUM; i++)
if (mask & (1 << i)) {
num_regs++; if (mask & (1 << i))
num_regs++;
if (dwarf_regs_mask & (1 << i))
num_dwarf_regs++;
}
gcc_assert (num_regs && num_regs <= 16); gcc_assert (num_regs && num_regs <= 16);
gcc_assert ((dwarf_regs_mask & ~mask) == 0);
/* We don't record the PC in the dwarf frame information. */
num_dwarf_regs = num_regs;
if (mask & (1 << PC_REGNUM))
num_dwarf_regs--;
/* For the body of the insn we are going to generate an UNSPEC in /* For the body of the insn we are going to generate an UNSPEC in
parallel with several USEs. This allows the insn to be recognized parallel with several USEs. This allows the insn to be recognized
...@@ -19660,14 +19665,13 @@ emit_multi_reg_push (unsigned long mask) ...@@ -19660,14 +19665,13 @@ emit_multi_reg_push (unsigned long mask)
gen_rtvec (1, reg), gen_rtvec (1, reg),
UNSPEC_PUSH_MULT)); UNSPEC_PUSH_MULT));
if (i != PC_REGNUM) if (dwarf_regs_mask & (1 << i))
{ {
tmp = gen_rtx_SET (VOIDmode, tmp = gen_rtx_SET (VOIDmode,
gen_frame_mem (SImode, stack_pointer_rtx), gen_frame_mem (SImode, stack_pointer_rtx),
reg); reg);
RTX_FRAME_RELATED_P (tmp) = 1; RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (dwarf, 0, dwarf_par_index) = tmp; XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
dwarf_par_index++;
} }
break; break;
...@@ -19682,7 +19686,7 @@ emit_multi_reg_push (unsigned long mask) ...@@ -19682,7 +19686,7 @@ emit_multi_reg_push (unsigned long mask)
XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg); XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
if (i != PC_REGNUM) if (dwarf_regs_mask & (1 << i))
{ {
tmp tmp
= gen_rtx_SET (VOIDmode, = gen_rtx_SET (VOIDmode,
...@@ -20689,7 +20693,7 @@ arm_expand_prologue (void) ...@@ -20689,7 +20693,7 @@ arm_expand_prologue (void)
/* Interrupt functions must not corrupt any registers. /* Interrupt functions must not corrupt any registers.
Creating a frame pointer however, corrupts the IP Creating a frame pointer however, corrupts the IP
register, so we must push it first. */ register, so we must push it first. */
emit_multi_reg_push (1 << IP_REGNUM); emit_multi_reg_push (1 << IP_REGNUM, 1 << IP_REGNUM);
/* Do not set RTX_FRAME_RELATED_P on this insn. /* Do not set RTX_FRAME_RELATED_P on this insn.
The dwarf stack unwinding code only wants to see one The dwarf stack unwinding code only wants to see one
...@@ -20750,7 +20754,8 @@ arm_expand_prologue (void) ...@@ -20750,7 +20754,8 @@ arm_expand_prologue (void)
if (cfun->machine->uses_anonymous_args) if (cfun->machine->uses_anonymous_args)
{ {
insn insn
= emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf); = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf,
(0xf0 >> (args_to_push / 4)) & 0xf);
emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx); emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
saved_pretend_args = 1; saved_pretend_args = 1;
} }
...@@ -20794,7 +20799,8 @@ arm_expand_prologue (void) ...@@ -20794,7 +20799,8 @@ arm_expand_prologue (void)
/* Push the argument registers, or reserve space for them. */ /* Push the argument registers, or reserve space for them. */
if (cfun->machine->uses_anonymous_args) if (cfun->machine->uses_anonymous_args)
insn = emit_multi_reg_push insn = emit_multi_reg_push
((0xf0 >> (args_to_push / 4)) & 0xf); ((0xf0 >> (args_to_push / 4)) & 0xf,
(0xf0 >> (args_to_push / 4)) & 0xf);
else else
insn = emit_insn insn = emit_insn
(gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
...@@ -20819,6 +20825,8 @@ arm_expand_prologue (void) ...@@ -20819,6 +20825,8 @@ arm_expand_prologue (void)
if (live_regs_mask) if (live_regs_mask)
{ {
unsigned long dwarf_regs_mask = live_regs_mask;
saved_regs += bit_count (live_regs_mask) * 4; saved_regs += bit_count (live_regs_mask) * 4;
if (optimize_size && !frame_pointer_needed if (optimize_size && !frame_pointer_needed
&& saved_regs == offsets->saved_regs - offsets->saved_args) && saved_regs == offsets->saved_regs - offsets->saved_args)
...@@ -20845,25 +20853,22 @@ arm_expand_prologue (void) ...@@ -20845,25 +20853,22 @@ arm_expand_prologue (void)
&& current_tune->prefer_ldrd_strd && current_tune->prefer_ldrd_strd
&& !optimize_function_for_size_p (cfun)) && !optimize_function_for_size_p (cfun))
{ {
gcc_checking_assert (live_regs_mask == dwarf_regs_mask);
if (TARGET_THUMB2) if (TARGET_THUMB2)
{ thumb2_emit_strd_push (live_regs_mask);
thumb2_emit_strd_push (live_regs_mask);
}
else if (TARGET_ARM else if (TARGET_ARM
&& !TARGET_APCS_FRAME && !TARGET_APCS_FRAME
&& !IS_INTERRUPT (func_type)) && !IS_INTERRUPT (func_type))
{ arm_emit_strd_push (live_regs_mask);
arm_emit_strd_push (live_regs_mask);
}
else else
{ {
insn = emit_multi_reg_push (live_regs_mask); insn = emit_multi_reg_push (live_regs_mask, live_regs_mask);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
} }
} }
else else
{ {
insn = emit_multi_reg_push (live_regs_mask); insn = emit_multi_reg_push (live_regs_mask, dwarf_regs_mask);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
} }
} }
...@@ -28694,7 +28699,13 @@ arm_dwarf_register_span (rtx rtl) ...@@ -28694,7 +28699,13 @@ arm_dwarf_register_span (rtx rtl)
/* Emit unwind directives for a store-multiple instruction or stack pointer /* Emit unwind directives for a store-multiple instruction or stack pointer
push during alignment. push during alignment.
These should only ever be generated by the function prologue code, so These should only ever be generated by the function prologue code, so
expect them to have a particular form. */ expect them to have a particular form.
The store-multiple instruction sometimes pushes pc as the last register,
although it should not be tracked into unwind information, or for -Os
sometimes pushes some dummy registers before first register that needs
to be tracked in unwind information; such dummy registers are there just
to avoid separate stack adjustment, and will not be restored in the
epilogue. */
static void static void
arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
...@@ -28705,32 +28716,43 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) ...@@ -28705,32 +28716,43 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
int reg_size; int reg_size;
unsigned reg; unsigned reg;
unsigned lastreg; unsigned lastreg;
unsigned padfirst = 0, padlast = 0;
rtx e; rtx e;
e = XVECEXP (p, 0, 0); e = XVECEXP (p, 0, 0);
if (GET_CODE (e) != SET) gcc_assert (GET_CODE (e) == SET);
abort ();
/* First insn will adjust the stack pointer. */ /* First insn will adjust the stack pointer. */
if (GET_CODE (e) != SET gcc_assert (GET_CODE (e) == SET
|| !REG_P (XEXP (e, 0)) && REG_P (SET_DEST (e))
|| REGNO (XEXP (e, 0)) != SP_REGNUM && REGNO (SET_DEST (e)) == SP_REGNUM
|| GET_CODE (XEXP (e, 1)) != PLUS) && GET_CODE (SET_SRC (e)) == PLUS);
abort ();
offset = -INTVAL (XEXP (XEXP (e, 1), 1)); offset = -INTVAL (XEXP (SET_SRC (e), 1));
nregs = XVECLEN (p, 0) - 1; nregs = XVECLEN (p, 0) - 1;
gcc_assert (nregs);
reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1)); reg = REGNO (SET_SRC (XVECEXP (p, 0, 1)));
if (reg < 16) if (reg < 16)
{ {
/* For -Os dummy registers can be pushed at the beginning to
avoid separate stack pointer adjustment. */
e = XVECEXP (p, 0, 1);
e = XEXP (SET_DEST (e), 0);
if (GET_CODE (e) == PLUS)
padfirst = INTVAL (XEXP (e, 1));
gcc_assert (padfirst == 0 || optimize_size);
/* The function prologue may also push pc, but not annotate it as it is /* The function prologue may also push pc, but not annotate it as it is
never restored. We turn this into a stack pointer adjustment. */ never restored. We turn this into a stack pointer adjustment. */
if (nregs * 4 == offset - 4) e = XVECEXP (p, 0, nregs);
{ e = XEXP (SET_DEST (e), 0);
fprintf (asm_out_file, "\t.pad #4\n"); if (GET_CODE (e) == PLUS)
offset -= 4; padlast = offset - INTVAL (XEXP (e, 1)) - 4;
} else
padlast = offset - 4;
gcc_assert (padlast == 0 || padlast == 4);
if (padlast == 4)
fprintf (asm_out_file, "\t.pad #4\n");
reg_size = 4; reg_size = 4;
fprintf (asm_out_file, "\t.save {"); fprintf (asm_out_file, "\t.save {");
} }
...@@ -28741,14 +28763,13 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) ...@@ -28741,14 +28763,13 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
} }
else else
/* Unknown register type. */ /* Unknown register type. */
abort (); gcc_unreachable ();
/* If the stack increment doesn't match the size of the saved registers, /* If the stack increment doesn't match the size of the saved registers,
something has gone horribly wrong. */ something has gone horribly wrong. */
if (offset != nregs * reg_size) gcc_assert (offset == padfirst + nregs * reg_size + padlast);
abort ();
offset = 0; offset = padfirst;
lastreg = 0; lastreg = 0;
/* The remaining insns will describe the stores. */ /* The remaining insns will describe the stores. */
for (i = 1; i <= nregs; i++) for (i = 1; i <= nregs; i++)
...@@ -28756,14 +28777,12 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) ...@@ -28756,14 +28777,12 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
/* Expect (set (mem <addr>) (reg)). /* Expect (set (mem <addr>) (reg)).
Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)). */ Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)). */
e = XVECEXP (p, 0, i); e = XVECEXP (p, 0, i);
if (GET_CODE (e) != SET gcc_assert (GET_CODE (e) == SET
|| !MEM_P (XEXP (e, 0)) && MEM_P (SET_DEST (e))
|| !REG_P (XEXP (e, 1))) && REG_P (SET_SRC (e)));
abort ();
reg = REGNO (XEXP (e, 1)); reg = REGNO (SET_SRC (e));
if (reg < lastreg) gcc_assert (reg >= lastreg);
abort ();
if (i != 1) if (i != 1)
fprintf (asm_out_file, ", "); fprintf (asm_out_file, ", ");
...@@ -28776,23 +28795,22 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) ...@@ -28776,23 +28795,22 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
/* Check that the addresses are consecutive. */ /* Check that the addresses are consecutive. */
e = XEXP (XEXP (e, 0), 0); e = XEXP (SET_DEST (e), 0);
if (GET_CODE (e) == PLUS) if (GET_CODE (e) == PLUS)
{ gcc_assert (REG_P (XEXP (e, 0))
offset += reg_size; && REGNO (XEXP (e, 0)) == SP_REGNUM
if (!REG_P (XEXP (e, 0)) && CONST_INT_P (XEXP (e, 1))
|| REGNO (XEXP (e, 0)) != SP_REGNUM && offset == INTVAL (XEXP (e, 1)));
|| !CONST_INT_P (XEXP (e, 1)) else
|| offset != INTVAL (XEXP (e, 1))) gcc_assert (i == 1
abort (); && REG_P (e)
} && REGNO (e) == SP_REGNUM);
else if (i != 1 offset += reg_size;
|| !REG_P (e)
|| REGNO (e) != SP_REGNUM)
abort ();
#endif #endif
} }
fprintf (asm_out_file, "}\n"); fprintf (asm_out_file, "}\n");
if (padfirst)
fprintf (asm_out_file, "\t.pad #%d\n", padfirst);
} }
/* Emit unwind directives for a SET. */ /* Emit unwind directives for a SET. */
......
2014-02-06 Jakub Jelinek <jakub@redhat.com> 2014-02-06 Jakub Jelinek <jakub@redhat.com>
PR target/59575
* gcc.target/arm/pr59575.c: New test.
PR debug/59992 PR debug/59992
* gcc.dg/pr59992.c: New test. * gcc.dg/pr59992.c: New test.
......
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