re PR debug/24444 (invalid register in debug info)

PR debug/24444
* config/ia64/ia64.c: Include debug.h.
(MAX_ARTIFICIAL_LABEL_BYTES): New.
(ia64_label_after_insn, ia64_dwarf2out_def_steady_cfa): New.
(IA64_CHANGE_CFA_IN_EPILOGUE): Define to 0.
(process_epilogue, process_set, process_for_unwind_directive):
Output unwind info only if requested.  Add CFA info if requested.
Add new arguments as needed.  Adjust callers.
* config/ia64/ia64.h (ARG_POINTER_CFA_OFFSET): Override
incorrect default.
(DWARF2_FRAME_INFO): Define to zero.
* config/ia64/unwind-ia64.c: Remove code that compensated for
the CFA offset error fixed above.
* config/ia64/t-ia64 (ia64.o): Depend on debug.h.
* dwarf2out.c (DWARF2_FRAME_INFO): Define default.
(dwarf2out_do_frame): Require nonzero DWARF2_UNWIND_INFO for
-funwind-tables and -fexceptions to enable frame info.
(dwarf2out_frame_init): Define initial CFA even if
DWARF2_UNWIND_INFO is disabled.  Call initial_return_save if
DWARF2_UNWIND_INFO is nonzero, not just defined.
(dwarf2out_frame_finish): Output non-EH call frame info only
if DWARF2_FRAME_INFO is nonzero.
(convert_cfa_to_loc_list,
compute_frame_pointer_to_cfa_displacement): Define even if
unwind info is not supported.
(gen_subprogram_die): Use the above unconditionally.  Remove
legacy alternate code.
* toplev.c (compile_file): Compile in call to
dwarf2out_frame_finish if DWARF2_DEBUGGING_INFO is defined.
(lang_dependent_init): Ditto for dwarf2out_frame_init.

From-SVN: r110594
This commit is contained in:
Alexandre Oliva 2006-02-04 22:08:04 +00:00 committed by Alexandre Oliva
parent 5460aa9c92
commit 658f32fda2
7 changed files with 206 additions and 75 deletions

View file

@ -1,3 +1,36 @@
2006-02-04 Alexandre Oliva <aoliva@redhat.com>
PR debug/24444
* config/ia64/ia64.c: Include debug.h.
(MAX_ARTIFICIAL_LABEL_BYTES): New.
(ia64_label_after_insn, ia64_dwarf2out_def_steady_cfa): New.
(IA64_CHANGE_CFA_IN_EPILOGUE): Define to 0.
(process_epilogue, process_set, process_for_unwind_directive):
Output unwind info only if requested. Add CFA info if requested.
Add new arguments as needed. Adjust callers.
* config/ia64/ia64.h (ARG_POINTER_CFA_OFFSET): Override
incorrect default.
(DWARF2_FRAME_INFO): Define to zero.
* config/ia64/unwind-ia64.c: Remove code that compensated for
the CFA offset error fixed above.
* config/ia64/t-ia64 (ia64.o): Depend on debug.h.
* dwarf2out.c (DWARF2_FRAME_INFO): Define default.
(dwarf2out_do_frame): Require nonzero DWARF2_UNWIND_INFO for
-funwind-tables and -fexceptions to enable frame info.
(dwarf2out_frame_init): Define initial CFA even if
DWARF2_UNWIND_INFO is disabled. Call initial_return_save if
DWARF2_UNWIND_INFO is nonzero, not just defined.
(dwarf2out_frame_finish): Output non-EH call frame info only
if DWARF2_FRAME_INFO is nonzero.
(convert_cfa_to_loc_list,
compute_frame_pointer_to_cfa_displacement): Define even if
unwind info is not supported.
(gen_subprogram_die): Use the above unconditionally. Remove
legacy alternate code.
* toplev.c (compile_file): Compile in call to
dwarf2out_frame_finish if DWARF2_DEBUGGING_INFO is defined.
(lang_dependent_init): Ditto for dwarf2out_frame_init.
2006-02-04 David Edelsohn <edelsohn@gnu.org>
Jakub Jelinek <jakub@redhat.com>

View file

@ -53,6 +53,7 @@ Boston, MA 02110-1301, USA. */
#include "cfglayout.h"
#include "tree-gimple.h"
#include "intl.h"
#include "debug.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
@ -190,8 +191,8 @@ static void final_emit_insn_group_barriers (FILE *);
static void emit_predicate_relation_info (void);
static void ia64_reorg (void);
static bool ia64_in_small_data_p (tree);
static void process_epilogue (void);
static int process_set (FILE *, rtx);
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 void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
@ -7971,29 +7972,84 @@ static bool last_block;
static bool need_copy_state;
#ifndef MAX_ARTIFICIAL_LABEL_BYTES
# define MAX_ARTIFICIAL_LABEL_BYTES 30
#endif
/* Emit a debugging label after a call-frame-related insn. We'd
rather output the label right away, but we'd have to output it
after, not before, the instruction, and the instruction has not
been output yet. So we emit the label after the insn, delete it to
avoid introducing basic blocks, and mark it as preserved, such that
it is still output, given that it is referenced in debug info. */
static const char *
ia64_emit_deleted_label_after_insn (rtx insn)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
rtx lb = gen_label_rtx ();
rtx label_insn = emit_label_after (lb, insn);
LABEL_PRESERVE_P (lb) = 1;
delete_insn (label_insn);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (label_insn));
return xstrdup (label);
}
/* Define the CFA after INSN with the steady-state definition. */
static void
ia64_dwarf2out_def_steady_cfa (rtx insn)
{
rtx fp = frame_pointer_needed
? hard_frame_pointer_rtx
: stack_pointer_rtx;
dwarf2out_def_cfa
(ia64_emit_deleted_label_after_insn (insn),
REGNO (fp),
ia64_initial_elimination_offset
(REGNO (arg_pointer_rtx), REGNO (fp))
+ ARG_POINTER_CFA_OFFSET (current_function_decl));
}
/* The generic dwarf2 frame debug info generator does not define a
separate region for the very end of the epilogue, so refrain from
doing so in the IA64-specific code as well. */
#define IA64_CHANGE_CFA_IN_EPILOGUE 0
/* The function emits unwind directives for the start of an epilogue. */
static void
process_epilogue (void)
process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame)
{
/* If this isn't the last block of the function, then we need to label the
current state, and copy it back in at the start of the next block. */
if (!last_block)
{
fprintf (asm_out_file, "\t.label_state %d\n",
++cfun->machine->state_num);
if (unwind)
fprintf (asm_out_file, "\t.label_state %d\n",
++cfun->machine->state_num);
need_copy_state = true;
}
fprintf (asm_out_file, "\t.restore sp\n");
if (unwind)
fprintf (asm_out_file, "\t.restore sp\n");
if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
dwarf2out_def_cfa (ia64_emit_deleted_label_after_insn (insn),
STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
}
/* This function processes a SET pattern looking for specific patterns
which result in emitting an assembly directive required for unwinding. */
static int
process_set (FILE *asm_out_file, rtx pat)
process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
{
rtx src = SET_SRC (pat);
rtx dest = SET_DEST (pat);
@ -8009,8 +8065,11 @@ process_set (FILE *asm_out_file, rtx pat)
/* If this is the final destination for ar.pfs, then this must
be the alloc in the prologue. */
if (dest_regno == current_frame_info.reg_save_ar_pfs)
fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
ia64_dbx_register_number (dest_regno));
{
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
@ -8021,8 +8080,9 @@ process_set (FILE *asm_out_file, rtx pat)
sp" now. */
if (current_frame_info.total_size == 0 && !frame_pointer_needed)
/* if haven't done process_epilogue() yet, do it now */
process_epilogue ();
fprintf (asm_out_file, "\t.prologue\n");
process_epilogue (asm_out_file, insn, unwind, frame);
if (unwind)
fprintf (asm_out_file, "\t.prologue\n");
}
return 1;
}
@ -8038,16 +8098,22 @@ process_set (FILE *asm_out_file, rtx pat)
gcc_assert (op0 == dest && GET_CODE (op1) == CONST_INT);
if (INTVAL (op1) < 0)
fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
-INTVAL (op1));
{
gcc_assert (!frame_pointer_needed);
if (unwind)
fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
-INTVAL (op1));
if (frame)
ia64_dwarf2out_def_steady_cfa (insn);
}
else
process_epilogue ();
process_epilogue (asm_out_file, insn, unwind, frame);
}
else
{
gcc_assert (GET_CODE (src) == REG
&& REGNO (src) == HARD_FRAME_POINTER_REGNUM);
process_epilogue ();
process_epilogue (asm_out_file, insn, unwind, frame);
}
return 1;
@ -8064,33 +8130,40 @@ process_set (FILE *asm_out_file, rtx pat)
case BR_REG (0):
/* Saving return address pointer. */
gcc_assert (dest_regno == current_frame_info.reg_save_b0);
fprintf (asm_out_file, "\t.save rp, r%d\n",
ia64_dbx_register_number (dest_regno));
if (unwind)
fprintf (asm_out_file, "\t.save rp, r%d\n",
ia64_dbx_register_number (dest_regno));
return 1;
case PR_REG (0):
gcc_assert (dest_regno == current_frame_info.reg_save_pr);
fprintf (asm_out_file, "\t.save pr, r%d\n",
ia64_dbx_register_number (dest_regno));
if (unwind)
fprintf (asm_out_file, "\t.save pr, r%d\n",
ia64_dbx_register_number (dest_regno));
return 1;
case AR_UNAT_REGNUM:
gcc_assert (dest_regno == current_frame_info.reg_save_ar_unat);
fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
ia64_dbx_register_number (dest_regno));
if (unwind)
fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
ia64_dbx_register_number (dest_regno));
return 1;
case AR_LC_REGNUM:
gcc_assert (dest_regno == current_frame_info.reg_save_ar_lc);
fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
ia64_dbx_register_number (dest_regno));
if (unwind)
fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
ia64_dbx_register_number (dest_regno));
return 1;
case STACK_POINTER_REGNUM:
gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed);
fprintf (asm_out_file, "\t.vframe r%d\n",
ia64_dbx_register_number (dest_regno));
if (unwind)
fprintf (asm_out_file, "\t.vframe r%d\n",
ia64_dbx_register_number (dest_regno));
if (frame)
ia64_dwarf2out_def_steady_cfa (insn);
return 1;
default:
@ -8135,35 +8208,41 @@ process_set (FILE *asm_out_file, rtx pat)
{
case BR_REG (0):
gcc_assert (!current_frame_info.reg_save_b0);
fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
if (unwind)
fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
return 1;
case PR_REG (0):
gcc_assert (!current_frame_info.reg_save_pr);
fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
if (unwind)
fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
return 1;
case AR_LC_REGNUM:
gcc_assert (!current_frame_info.reg_save_ar_lc);
fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
if (unwind)
fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
return 1;
case AR_PFS_REGNUM:
gcc_assert (!current_frame_info.reg_save_ar_pfs);
fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
if (unwind)
fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
return 1;
case AR_UNAT_REGNUM:
gcc_assert (!current_frame_info.reg_save_ar_unat);
fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
if (unwind)
fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
return 1;
case GR_REG (4):
case GR_REG (5):
case GR_REG (6):
case GR_REG (7):
fprintf (asm_out_file, "\t.save.g 0x%x\n",
1 << (src_regno - GR_REG (4)));
if (unwind)
fprintf (asm_out_file, "\t.save.g 0x%x\n",
1 << (src_regno - GR_REG (4)));
return 1;
case BR_REG (1):
@ -8171,24 +8250,27 @@ process_set (FILE *asm_out_file, rtx pat)
case BR_REG (3):
case BR_REG (4):
case BR_REG (5):
fprintf (asm_out_file, "\t.save.b 0x%x\n",
1 << (src_regno - BR_REG (1)));
if (unwind)
fprintf (asm_out_file, "\t.save.b 0x%x\n",
1 << (src_regno - BR_REG (1)));
return 1;
case FR_REG (2):
case FR_REG (3):
case FR_REG (4):
case FR_REG (5):
fprintf (asm_out_file, "\t.save.f 0x%x\n",
1 << (src_regno - FR_REG (2)));
if (unwind)
fprintf (asm_out_file, "\t.save.f 0x%x\n",
1 << (src_regno - FR_REG (2)));
return 1;
case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
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):
fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
1 << (src_regno - FR_REG (12)));
if (unwind)
fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
1 << (src_regno - FR_REG (12)));
return 1;
default:
@ -8205,8 +8287,11 @@ process_set (FILE *asm_out_file, rtx pat)
void
process_for_unwind_directive (FILE *asm_out_file, rtx insn)
{
if (flag_unwind_tables
|| (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
bool unwind = (flag_unwind_tables
|| (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
bool frame = dwarf2out_do_frame ();
if (unwind || frame)
{
rtx pat;
@ -8218,9 +8303,14 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
/* Restore unwind state from immediately before the epilogue. */
if (need_copy_state)
{
fprintf (asm_out_file, "\t.body\n");
fprintf (asm_out_file, "\t.copy_state %d\n",
cfun->machine->state_num);
if (unwind)
{
fprintf (asm_out_file, "\t.body\n");
fprintf (asm_out_file, "\t.copy_state %d\n",
cfun->machine->state_num);
}
if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
ia64_dwarf2out_def_steady_cfa (insn);
need_copy_state = false;
}
}
@ -8237,7 +8327,7 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
switch (GET_CODE (pat))
{
case SET:
process_set (asm_out_file, pat);
process_set (asm_out_file, pat, insn, unwind, frame);
break;
case PARALLEL:
@ -8248,7 +8338,7 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
{
rtx x = XVECEXP (pat, 0, par_index);
if (GET_CODE (x) == SET)
process_set (asm_out_file, x);
process_set (asm_out_file, x, insn, unwind, frame);
}
break;
}

View file

@ -981,6 +981,12 @@ enum reg_class
On some machines it may depend on the data type of the function. */
#define FIRST_PARM_OFFSET(FUNDECL) 0
/* The CFA is defined as the SP at the call site, so we have to take
into account that the first argument pointer is
STACK_POINTER_OFFSET bytes off the stack pointer. */
#define ARG_POINTER_CFA_OFFSET(FNDECL) \
(FIRST_PARM_OFFSET (FNDECL) - STACK_POINTER_OFFSET)
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame, after the
prologue. */
@ -1867,6 +1873,12 @@ do { \
#define DWARF2_DEBUGGING_INFO 1
/* We do not want call-frame info to be output, since debuggers are
supposed to use the target unwind info. Leave this undefined it
TARGET_UNWIND_INFO might ever be false. */
#define DWARF2_FRAME_INFO 0
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DWARF2_ASM)
/* Use tags for debug info labels, so that they don't break instruction

View file

@ -50,3 +50,5 @@ ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
# genattrtab generates very long string literals.
insn-attrtab.o-warn = -Wno-error
ia64.o: debug.h

View file

@ -2067,7 +2067,7 @@ uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
}
/* Fill in CONTEXT for top-of-stack. The only valid registers at this
level will be the return address and the CFA. Note that CFA = SP+16. */
level will be the return address and the CFA. */
#define uw_init_context(CONTEXT) \
do { \
@ -2083,7 +2083,7 @@ uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
{
void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
/* Set psp to the caller's stack pointer. */
void *psp = __builtin_dwarf_cfa () - 16;
void *psp = __builtin_dwarf_cfa ();
_Unwind_FrameState fs;
unsigned long rnat, tmp1, tmp2;

View file

@ -90,20 +90,31 @@ static void dwarf2out_source_line (unsigned int, const char *);
DW_CFA_... = DWARF2 CFA call frame instruction
DW_TAG_... = DWARF2 DIE tag */
#ifndef DWARF2_FRAME_INFO
# ifdef DWARF2_DEBUGGING_INFO
# define DWARF2_FRAME_INFO \
(write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
# else
# define DWARF2_FRAME_INFO 0
# endif
#endif
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
int
dwarf2out_do_frame (void)
{
/* We want to emit correct CFA location expressions or lists, so we
have to return true if we're going to output debug info, even if
we're not going to output frame or unwind info. */
return (write_symbols == DWARF2_DEBUG
|| write_symbols == VMS_AND_DWARF2_DEBUG
#ifdef DWARF2_FRAME_INFO
|| DWARF2_FRAME_INFO
#endif
#ifdef DWARF2_UNWIND_INFO
|| flag_unwind_tables
|| (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)
|| (DWARF2_UNWIND_INFO
&& (flag_unwind_tables
|| (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)))
#endif
);
}
@ -2586,10 +2597,12 @@ dwarf2out_frame_init (void)
/* Generate the CFA instructions common to all FDE's. Do it now for the
sake of lookup_cfa. */
#ifdef DWARF2_UNWIND_INFO
/* On entry, the Canonical Frame Address is at SP. */
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
initial_return_save (INCOMING_RETURN_ADDR_RTX);
#ifdef DWARF2_UNWIND_INFO
if (DWARF2_UNWIND_INFO)
initial_return_save (INCOMING_RETURN_ADDR_RTX);
#endif
}
@ -2597,12 +2610,7 @@ void
dwarf2out_frame_finish (void)
{
/* Output call frame information. */
if (write_symbols == DWARF2_DEBUG
|| write_symbols == VMS_AND_DWARF2_DEBUG
#ifdef DWARF2_FRAME_INFO
|| DWARF2_FRAME_INFO
#endif
)
if (DWARF2_FRAME_INFO)
output_call_frame_info (0);
#ifndef TARGET_UNWIND_INFO
@ -10326,7 +10334,6 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
add_const_value_attribute (var_die, rtl);
}
#ifdef DWARF2_UNWIND_INFO
/* Convert the CFI instructions for the current function into a location
list. This is used for DW_AT_frame_base when we targeting a dwarf2
consumer that does not support the dwarf3 DW_OP_call_frame_cfa. */
@ -10433,7 +10440,6 @@ compute_frame_pointer_to_cfa_displacement (void)
frame_pointer_cfa_offset = -offset;
}
#endif
/* Generate a DW_AT_name attribute given some string value to be included as
the value of the attribute. */
@ -11668,7 +11674,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde);
#endif
#ifdef DWARF2_UNWIND_INFO
/* We define the "frame base" as the function's CFA. This is more
convenient for several reasons: (1) It's stable across the prologue
and epilogue, which makes it better than just a frame pointer,
@ -11695,17 +11700,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
debugger about. We'll need to adjust all frame_base references
by this displacement. */
compute_frame_pointer_to_cfa_displacement ();
#else
/* For targets which support DWARF2, but not DWARF2 call-frame info,
we just use the stack pointer or frame pointer. */
/* ??? Should investigate getting better info via callbacks, or else
by interpreting the IA-64 unwind info. */
{
rtx fp_reg
= frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
}
#endif
if (cfun->static_chain_decl)
add_AT_location_description (subr_die, DW_AT_static_link,

View file

@ -1028,7 +1028,7 @@ compile_file (void)
/* Do dbx symbols. */
timevar_push (TV_SYMOUT);
#ifdef DWARF2_UNWIND_INFO
#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_finish ();
#endif
@ -1868,7 +1868,7 @@ lang_dependent_init (const char *name)
predefined types. */
timevar_push (TV_SYMOUT);
#ifdef DWARF2_UNWIND_INFO
#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_init ();
#endif