Commit 469ac993 by Jason Merrill

x

From-SVN: r13305
parent 97adc6ed
...@@ -1832,6 +1832,7 @@ ix86_expand_prologue () ...@@ -1832,6 +1832,7 @@ ix86_expand_prologue ()
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool); || current_function_uses_const_pool);
long tsize = get_frame_size (); long tsize = get_frame_size ();
rtx insn;
if (!TARGET_SCHEDULE_PROLOGUE) if (!TARGET_SCHEDULE_PROLOGUE)
return; return;
...@@ -1841,17 +1842,23 @@ ix86_expand_prologue () ...@@ -1841,17 +1842,23 @@ ix86_expand_prologue ()
xops[2] = GEN_INT (tsize); xops[2] = GEN_INT (tsize);
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
emit_insn (gen_rtx (SET, 0, insn = emit_insn
(gen_rtx (SET, 0,
gen_rtx (MEM, SImode, gen_rtx (MEM, SImode,
gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)), gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
frame_pointer_rtx)); frame_pointer_rtx));
emit_move_insn (xops[1], xops[0]); RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (xops[1], xops[0]);
RTX_FRAME_RELATED_P (insn) = 1;
} }
if (tsize == 0) if (tsize == 0)
; ;
else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT) else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)
emit_insn (gen_subsi3 (xops[0], xops[0], xops[2])); {
insn = emit_insn (gen_subsi3 (xops[0], xops[0], xops[2]));
RTX_FRAME_RELATED_P (insn) = 1;
}
else else
{ {
xops[3] = gen_rtx (REG, SImode, 0); xops[3] = gen_rtx (REG, SImode, 0);
...@@ -1877,10 +1884,13 @@ ix86_expand_prologue () ...@@ -1877,10 +1884,13 @@ ix86_expand_prologue ()
|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
{ {
xops[0] = gen_rtx (REG, SImode, regno); xops[0] = gen_rtx (REG, SImode, regno);
emit_insn (gen_rtx (SET, 0, insn = emit_insn
(gen_rtx (SET, 0,
gen_rtx (MEM, SImode, gen_rtx (MEM, SImode,
gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)), gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
xops[0])); xops[0]));
RTX_FRAME_RELATED_P (insn) = 1;
} }
if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION) if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
......
...@@ -2331,6 +2331,13 @@ number as al, and ax. ...@@ -2331,6 +2331,13 @@ number as al, and ax.
(n) == 7 ? 5 : \ (n) == 7 ? 5 : \
(n) + 4) (n) + 4)
/* Before the prologue, RA is at 0(%esp). */
#define INCOMING_RETURN_ADDR_RTX \
gen_rtx (MEM, VOIDmode, gen_rtx (REG, VOIDmode, STACK_POINTER_REGNUM))
/* PC is dbx register 8; let's use that column for RA. */
#define DWARF_FRAME_RETURN_COLUMN 8
/* This is how to output the definition of a user-level label named NAME, /* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */ such as the label on a static function or variable NAME. */
......
...@@ -5068,22 +5068,7 @@ save_restore_insns (store_p, large_reg, large_offset, file) ...@@ -5068,22 +5068,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
if (store_p) if (store_p)
{ {
rtx insn = emit_move_insn (mem_rtx, reg_rtx); rtx insn = emit_move_insn (mem_rtx, reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
if (write_symbols == DWARF2_DEBUG)
{
int offset = (gp_offset
- current_frame_info.total_size);
if (regno == GP_REG_FIRST + 31)
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_RETURN_SAVE,
GEN_INT (offset), REG_NOTES (insn));
else
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_SAVE,
gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
GEN_INT (offset)),
REG_NOTES (insn));
}
} }
else if (!TARGET_ABICALLS || mips_abi != ABI_32 else if (!TARGET_ABICALLS || mips_abi != ABI_32
|| regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST)) || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
...@@ -5199,17 +5184,7 @@ save_restore_insns (store_p, large_reg, large_offset, file) ...@@ -5199,17 +5184,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
if (store_p) if (store_p)
{ {
rtx insn = emit_move_insn (mem_rtx, reg_rtx); rtx insn = emit_move_insn (mem_rtx, reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
if (write_symbols == DWARF2_DEBUG)
{
int offset = (gp_offset
- current_frame_info.total_size);
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_SAVE,
gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
GEN_INT (offset)),
REG_NOTES (insn));
}
} }
else else
emit_move_insn (reg_rtx, mem_rtx); emit_move_insn (reg_rtx, mem_rtx);
...@@ -5452,12 +5427,7 @@ mips_expand_prologue () ...@@ -5452,12 +5427,7 @@ mips_expand_prologue ()
insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx)); tsize_rtx));
if (write_symbols == DWARF2_DEBUG) RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_FRAME,
gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
GEN_INT (tsize)),
REG_NOTES (insn));
} }
save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0); save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0);
...@@ -5471,12 +5441,7 @@ mips_expand_prologue () ...@@ -5471,12 +5441,7 @@ mips_expand_prologue ()
else else
insn= emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); insn= emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
if (write_symbols == DWARF2_DEBUG) RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_FRAME,
gen_rtx (PLUS, VOIDmode, frame_pointer_rtx,
GEN_INT (tsize)),
REG_NOTES (insn));
} }
if (TARGET_ABICALLS && mips_abi != ABI_32) if (TARGET_ABICALLS && mips_abi != ABI_32)
......
...@@ -927,11 +927,16 @@ while (0) ...@@ -927,11 +927,16 @@ while (0)
This mapping does not allow for tracking DBX register 0, since column 0 This mapping does not allow for tracking DBX register 0, since column 0
is used for the frame address, but since register 0 is fixed this is is used for the frame address, but since register 0 is fixed this is
not really a problem. */ not really a problem. */
#define DWARF_FRAME_REGNUM(REG) (DBX_REGISTER_NUMBER (REG)) #define DWARF_FRAME_REGNUM(REG) \
(REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN \
: DBX_REGISTER_NUMBER (REG))
/* The DWARF 2 CFA column which tracks the return address. */ /* The DWARF 2 CFA column which tracks the return address. */
#define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1) #define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)
/* Before the prologue, RA lives in r31. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31)
/* Overrides for the COFF debug format. */ /* Overrides for the COFF debug format. */
#define PUT_SDB_SCL(a) \ #define PUT_SDB_SCL(a) \
do { \ do { \
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc. Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
Contributed by Gary Funck (gary@intrepid.com). Derived from the Contributed by Gary Funck (gary@intrepid.com). Derived from the
DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com). DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com).
Extensively modified by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC. This file is part of GNU CC.
...@@ -23,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -23,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef DWARF2_DEBUGGING_INFO #ifdef DWARF2_DEBUGGING_INFO
#include <stdio.h> #include <stdio.h>
#include <setjmp.h>
#include "dwarf2.h" #include "dwarf2.h"
#include "tree.h" #include "tree.h"
#include "flags.h" #include "flags.h"
...@@ -67,7 +69,8 @@ typedef enum ...@@ -67,7 +69,8 @@ typedef enum
dw_val_class_loc, dw_val_class_loc,
dw_val_class_const, dw_val_class_const,
dw_val_class_unsigned_const, dw_val_class_unsigned_const,
dw_val_class_double_const, dw_val_class_long_long,
dw_val_class_float,
dw_val_class_flag, dw_val_class_flag,
dw_val_class_die_ref, dw_val_class_die_ref,
dw_val_class_fde_ref, dw_val_class_fde_ref,
...@@ -95,12 +98,20 @@ typedef struct pubname_struct *pubname_ref; ...@@ -95,12 +98,20 @@ typedef struct pubname_struct *pubname_ref;
typedef dw_die_ref *arange_ref; typedef dw_die_ref *arange_ref;
/* Describe a double word constant value. */ /* Describe a double word constant value. */
typedef struct dw_double_const_struct typedef struct dw_long_long_struct
{ {
unsigned long dw_dbl_hi; unsigned long hi;
unsigned long dw_dbl_low; unsigned long low;
} }
dw_dbl_const; dw_long_long_const;
/* Describe a floating point constant value. */
typedef struct dw_fp_struct
{
long *array;
unsigned length;
}
dw_float_const;
/* Each entry in the line_info_table maintains the file and /* Each entry in the line_info_table maintains the file and
line nuber associated with the label generated for that line nuber associated with the label generated for that
...@@ -134,7 +145,8 @@ typedef struct dw_val_struct ...@@ -134,7 +145,8 @@ typedef struct dw_val_struct
dw_loc_descr_ref val_loc; dw_loc_descr_ref val_loc;
long int val_int; long int val_int;
long unsigned val_unsigned; long unsigned val_unsigned;
dw_dbl_const val_dbl_const; dw_long_long_const val_long_long;
dw_float_const val_float;
dw_die_ref val_die_ref; dw_die_ref val_die_ref;
unsigned val_fde_index; unsigned val_fde_index;
char *val_str; char *val_str;
...@@ -301,7 +313,11 @@ extern char *language_string; ...@@ -301,7 +313,11 @@ extern char *language_string;
static unsigned cie_size; static unsigned cie_size;
/* Offsets recorded in opcodes are a multiple of this alignment factor. */ /* Offsets recorded in opcodes are a multiple of this alignment factor. */
#define DWARF_CIE_DATA_ALIGNMENT -4 #ifdef STACK_GROWS_DOWNWARD
#define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_WORD)
#else
#define DWARF_CIE_DATA_ALIGNMENT UNITS_PER_WORD
#endif
/* Fixed size portion of the FDE. */ /* Fixed size portion of the FDE. */
#define DWARF_FDE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2 * PTR_SIZE) #define DWARF_FDE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2 * PTR_SIZE)
...@@ -830,9 +846,9 @@ char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ...@@ -830,9 +846,9 @@ char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
#endif #endif
/* The mapping from gcc register number to DWARF 2 CFA column number. By /* The mapping from gcc register number to DWARF 2 CFA column number. By
default, we provide columns for all registers after the CFA column. */ default, we just provide columns for all registers. */
#ifndef DWARF_FRAME_REGNUM #ifndef DWARF_FRAME_REGNUM
#define DWARF_FRAME_REGNUM(REG) (DBX_REGISTER_NUMBER (REG) + 1) #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif #endif
/************************ general utility functions **************************/ /************************ general utility functions **************************/
...@@ -1948,7 +1964,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val) ...@@ -1948,7 +1964,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
/* Add an unsigned double integer attribute value to a DIE. */ /* Add an unsigned double integer attribute value to a DIE. */
inline void inline void
add_AT_double (die, attr_kind, val_hi, val_low) add_AT_long_long (die, attr_kind, val_hi, val_low)
register dw_die_ref die; register dw_die_ref die;
register enum dwarf_attribute attr_kind; register enum dwarf_attribute attr_kind;
register unsigned long val_hi; register unsigned long val_hi;
...@@ -1959,9 +1975,29 @@ add_AT_double (die, attr_kind, val_hi, val_low) ...@@ -1959,9 +1975,29 @@ add_AT_double (die, attr_kind, val_hi, val_low)
{ {
attr->dw_attr_next = NULL; attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind; attr->dw_attr = attr_kind;
attr->dw_attr_val.val_class = dw_val_class_double_const; attr->dw_attr_val.val_class = dw_val_class_long_long;
attr->dw_attr_val.v.val_dbl_const.dw_dbl_hi = val_hi; attr->dw_attr_val.v.val_long_long.hi = val_hi;
attr->dw_attr_val.v.val_dbl_const.dw_dbl_low = val_low; attr->dw_attr_val.v.val_long_long.low = val_low;
add_dwarf_attr (die, attr);
}
}
/* Add a floating point attribute value to a DIE and return it. */
inline void
add_AT_float (die, attr_kind, length, array)
register dw_die_ref die;
register enum dwarf_attribute attr_kind;
register unsigned length;
register long *array;
{
register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
if (attr != NULL)
{
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
attr->dw_attr_val.val_class = dw_val_class_float;
attr->dw_attr_val.v.val_float.length = length;
attr->dw_attr_val.v.val_float.array = array;
add_dwarf_attr (die, attr); add_dwarf_attr (die, attr);
} }
} }
...@@ -2502,10 +2538,13 @@ print_die (die, outfile) ...@@ -2502,10 +2538,13 @@ print_die (die, outfile)
case dw_val_class_unsigned_const: case dw_val_class_unsigned_const:
fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned); fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned);
break; break;
case dw_val_class_double_const: case dw_val_class_long_long:
fprintf (outfile, "constant (%u,%u)", fprintf (outfile, "constant (%u,%u)",
a->dw_attr_val.v.val_dbl_const.dw_dbl_hi, a->dw_attr_val.v.val_long_long.hi,
a->dw_attr_val.v.val_dbl_const.dw_dbl_low); a->dw_attr_val.v.val_long_long.low);
break;
case dw_val_class_float:
fprintf (outfile, "floating-point constant");
break; break;
case dw_val_class_flag: case dw_val_class_flag:
fprintf (outfile, "%u", a->dw_attr_val.v.val_flag); fprintf (outfile, "%u", a->dw_attr_val.v.val_flag);
...@@ -2909,8 +2948,11 @@ size_of_die (die) ...@@ -2909,8 +2948,11 @@ size_of_die (die)
case dw_val_class_unsigned_const: case dw_val_class_unsigned_const:
size += constant_size (a->dw_attr_val.v.val_unsigned); size += constant_size (a->dw_attr_val.v.val_unsigned);
break; break;
case dw_val_class_double_const: case dw_val_class_long_long:
size += 8; size += 1 + 8; /* block */
break;
case dw_val_class_float:
size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */
break; break;
case dw_val_class_flag: case dw_val_class_flag:
size += 1; size += 1;
...@@ -3237,8 +3279,10 @@ value_format (v) ...@@ -3237,8 +3279,10 @@ value_format (v)
default: default:
abort (); abort ();
} }
case dw_val_class_double_const: case dw_val_class_long_long:
return DW_FORM_data8; return DW_FORM_block1;
case dw_val_class_float:
return DW_FORM_block1;
case dw_val_class_flag: case dw_val_class_flag:
return DW_FORM_flag; return DW_FORM_flag;
case dw_val_class_die_ref: case dw_val_class_die_ref:
...@@ -3342,9 +3386,7 @@ output_loc_operands (loc) ...@@ -3342,9 +3386,7 @@ output_loc_operands (loc)
break; break;
case DW_OP_const8u: case DW_OP_const8u:
case DW_OP_const8s: case DW_OP_const8s:
ASM_OUTPUT_DWARF_DATA8 (asm_out_file, abort ();
val1->v.val_dbl_const.dw_dbl_hi,
val2->v.val_dbl_const.dw_dbl_low);
fputc ('\n', asm_out_file); fputc ('\n', asm_out_file);
break; break;
case DW_OP_constu: case DW_OP_constu:
...@@ -3459,6 +3501,8 @@ output_die (die) ...@@ -3459,6 +3501,8 @@ output_die (die)
register unsigned long ref_offset; register unsigned long ref_offset;
register unsigned long size; register unsigned long size;
register dw_loc_descr_ref loc; register dw_loc_descr_ref loc;
register int i;
output_uleb128 (die->die_abbrev); output_uleb128 (die->die_abbrev);
if (flag_verbose_asm) if (flag_verbose_asm)
fprintf (asm_out_file, " (DIE (0x%x) %s)", fprintf (asm_out_file, " (DIE (0x%x) %s)",
...@@ -3530,10 +3574,36 @@ output_die (die) ...@@ -3530,10 +3574,36 @@ output_die (die)
abort (); abort ();
} }
break; break;
case dw_val_class_double_const: case dw_val_class_long_long:
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 8);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s %s",
ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA8 (asm_out_file, ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
a->dw_attr_val.v.val_dbl_const.dw_dbl_hi, a->dw_attr_val.v.val_long_long.hi,
a->dw_attr_val.v.val_dbl_const.dw_dbl_low); a->dw_attr_val.v.val_long_long.low);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s long long constant",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
break;
case dw_val_class_float:
ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
a->dw_attr_val.v.val_float.length * 4);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s %s",
ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
fputc ('\n', asm_out_file);
for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
{
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
a->dw_attr_val.v.val_float.array[i]);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s fp constant word %d",
ASM_COMMENT_START, i);
fputc ('\n', asm_out_file);
}
break; break;
case dw_val_class_flag: case dw_val_class_flag:
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag); ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
...@@ -3571,7 +3641,9 @@ output_die (die) ...@@ -3571,7 +3641,9 @@ output_die (die)
default: default:
abort (); abort ();
} }
if (a->dw_attr_val.val_class != dw_val_class_loc) if (a->dw_attr_val.val_class != dw_val_class_loc
&& a->dw_attr_val.val_class != dw_val_class_long_long
&& a->dw_attr_val.val_class != dw_val_class_float)
{ {
if (flag_verbose_asm) if (flag_verbose_asm)
{ {
...@@ -3631,35 +3703,23 @@ output_compilation_unit_header () ...@@ -3631,35 +3703,23 @@ output_compilation_unit_header ()
fputc ('\n', asm_out_file); fputc ('\n', asm_out_file);
} }
/* Extract the register and offset values from RTL. If no register number /* Generate a new label for the CFI info to refer to. */
is specified, return -1 to indicate frame-relative addressing. */
static void char *
decode_cfi_rtl (rtl, regp, offsetp) dwarf2out_cfi_label ()
register rtx rtl;
register unsigned long *regp;
register long *offsetp;
{ {
switch (GET_CODE (rtl)) static char label[20];
{ static unsigned long label_num = 0;
case REG:
*regp = reg_number (rtl); ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++);
*offsetp = 0; ASM_OUTPUT_LABEL (asm_out_file, label);
break;
case PLUS: return label;
*regp = reg_number (XEXP (rtl, 0));
*offsetp = INTVAL (XEXP (rtl, 1));
break;
case CONST_INT:
*regp = (unsigned long) -1;
*offsetp = INTVAL (rtl);
break;
default:
abort ();
}
} }
/* Add CFI to the current fde at the PC value indicated by LABEL if specified, /* Add CFI to the current fde at the PC value indicated by LABEL if specified,
or to the CIE if LABEL is NULL. */ or to the CIE if LABEL is NULL. */
static void static void
add_fde_cfi (label, cfi) add_fde_cfi (label, cfi)
register char * label; register char * label;
...@@ -3668,6 +3728,8 @@ add_fde_cfi (label, cfi) ...@@ -3668,6 +3728,8 @@ add_fde_cfi (label, cfi)
if (label) if (label)
{ {
register dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
if (*label == 0)
label = dwarf2out_cfi_label ();
if (fde->dw_fde_current_label == NULL if (fde->dw_fde_current_label == NULL
|| strcmp (label, fde->dw_fde_current_label) != 0) || strcmp (label, fde->dw_fde_current_label) != 0)
{ {
...@@ -3730,20 +3792,20 @@ lookup_cfa (regp, offsetp) ...@@ -3730,20 +3792,20 @@ lookup_cfa (regp, offsetp)
} }
/* Entry point to update the canonical frame address (CFA). /* Entry point to update the canonical frame address (CFA).
LABEL is passed to add_fde_cfi. RTL is either: LABEL is passed to add_fde_cfi. The value of CFA is now to be
calculated from REG+OFFSET. */
a REG: The frame is at 0(REG).
a PLUS of a REG and a CONST_INT: The frame is at CONST(REG). */
void void
dwarf2out_def_cfa (label, rtl) dwarf2out_def_cfa (label, reg, offset)
register char * label; register char * label;
register rtx rtl; register unsigned reg;
register long offset;
{ {
register dw_cfi_ref cfi; register dw_cfi_ref cfi;
unsigned long reg, old_reg; unsigned old_reg;
long offset, old_offset; long old_offset;
decode_cfi_rtl (rtl, &reg, &offset); reg = DWARF_FRAME_REGNUM (reg);
lookup_cfa (&old_reg, &old_offset); lookup_cfa (&old_reg, &old_offset);
if (reg == old_reg && offset == old_offset) if (reg == old_reg && offset == old_offset)
...@@ -3775,29 +3837,21 @@ dwarf2out_def_cfa (label, rtl) ...@@ -3775,29 +3837,21 @@ dwarf2out_def_cfa (label, rtl)
/* Add the CFI for saving a register. REG is the CFA column number. /* Add the CFI for saving a register. REG is the CFA column number.
LABEL is passed to add_fde_cfi. LABEL is passed to add_fde_cfi.
RTL is either: If SREG is -1, the register is saved at OFFSET from the CFA;
otherwise it is saved in SREG. */
a REG: The register is saved in REG.
a CONST_INT: The register is saved at an offset of CONST
from the CFA. */
static void static void
reg_save (label, reg, rtl) reg_save (label, reg, sreg, offset)
register char * label; register char * label;
register unsigned long reg; register unsigned reg;
register rtx rtl; register unsigned sreg;
register long offset;
{ {
register dw_cfi_ref cfi; register dw_cfi_ref cfi = new_cfi ();
unsigned long sreg;
long offset;
cfi = new_cfi ();
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
decode_cfi_rtl (rtl, &sreg, &offset); if (sreg == -1)
offset /= DWARF_CIE_DATA_ALIGNMENT;
if (sreg == (unsigned long) -1)
{ {
if (reg & ~0x3f) if (reg & ~0x3f)
/* The register number won't fit in 6 bits, so we have to use /* The register number won't fit in 6 bits, so we have to use
...@@ -3805,6 +3859,9 @@ reg_save (label, reg, rtl) ...@@ -3805,6 +3859,9 @@ reg_save (label, reg, rtl)
cfi->dw_cfi_opc = DW_CFA_offset_extended; cfi->dw_cfi_opc = DW_CFA_offset_extended;
else else
cfi->dw_cfi_opc = DW_CFA_offset; cfi->dw_cfi_opc = DW_CFA_offset;
offset /= DWARF_CIE_DATA_ALIGNMENT;
assert (offset >= 0);
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
} }
else else
...@@ -3817,24 +3874,166 @@ reg_save (label, reg, rtl) ...@@ -3817,24 +3874,166 @@ reg_save (label, reg, rtl)
} }
/* Entry point for saving a register. REG is the GCC register number. /* Entry point for saving a register. REG is the GCC register number.
LABEL and RTL are passed to reg_save. */ LABEL and OFFSET are passed to reg_save. */
void void
dwarf2out_reg_save (label, reg, rtl) dwarf2out_reg_save (label, reg, offset)
register char * label; register char * label;
register unsigned long reg; register unsigned reg;
register long offset;
{
reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
}
/* Record the initial position of the return address. RTL is
INCOMING_RETURN_ADDR_RTX. */
static void
initial_return_save (rtl)
register rtx rtl; register rtx rtl;
{ {
reg_save (label, DWARF_FRAME_REGNUM (reg), rtl); unsigned reg = -1;
long offset = 0;
switch (GET_CODE (rtl))
{
case REG:
/* RA is in a register. */
reg = reg_number (rtl);
break;
case MEM:
/* RA is on the stack. */
rtl = XEXP (rtl, 0);
switch (GET_CODE (rtl))
{
case REG:
assert (REGNO (rtl) == STACK_POINTER_REGNUM);
offset = 0;
break;
case PLUS:
assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
offset = INTVAL (XEXP (rtl, 1));
break;
case MINUS:
assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
offset = -INTVAL (XEXP (rtl, 1));
break;
default:
abort ();
}
break;
default:
abort ();
}
reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset);
} }
/* Entry point for saving the return address. /* Record call frame debugging information for INSN, which either
LABEL and RTL are passed to reg_save. */ sets SP or FP (adjusting how we calculate the frame address) or saves a
register to the stack. If INSN is NULL_RTX, initialize our state. */
void void
dwarf2out_return_save (label, rtl) dwarf2out_frame_debug (insn)
register char * label; rtx insn;
register rtx rtl;
{ {
reg_save (label, DWARF_FRAME_RETURN_COLUMN, rtl); char *label;
rtx src, dest;
long offset;
static unsigned cfa_reg;
static long cfa_offset;
static long cfa_sp_offset;
if (insn == NULL_RTX)
{
/* Set up state for generating call frame debug info. */
cfa_reg = STACK_POINTER_REGNUM;
cfa_offset = 0;
cfa_sp_offset = 0;
return;
}
label = dwarf2out_cfi_label ();
insn = PATTERN (insn);
assert (GET_CODE (insn) == SET);
src = SET_SRC (insn);
dest = SET_DEST (insn);
switch (GET_CODE (dest))
{
case REG:
/* Update the CFA rule wrt SP or FP. Make sure src is
relative to the current CFA register. */
assert (REGNO (dest) == STACK_POINTER_REGNUM
|| frame_pointer_needed && REGNO (dest) == FRAME_POINTER_REGNUM);
switch (GET_CODE (src))
{
/* Setting FP from SP. */
case REG:
assert (cfa_reg == REGNO (src));
cfa_reg = REGNO (dest);
break;
/* Adjusting SP. */
case PLUS:
cfa_sp_offset -= INTVAL (XEXP (src, 1));
goto add;
case MINUS:
cfa_sp_offset += INTVAL (XEXP (src, 1));
add:
assert (REGNO (XEXP (src, 0)) == STACK_POINTER_REGNUM);
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset = cfa_sp_offset;
break;
default:
abort ();
}
dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
break;
case MEM:
/* Saving a register to the stack. Make sure dest is relative to the
CFA register. */
assert (GET_CODE (src) == REG);
switch (GET_CODE (XEXP (dest, 0)))
{
/* With a push. */
case PRE_DEC:
cfa_sp_offset += GET_MODE_SIZE (GET_MODE (dest));
goto pre;
case PRE_INC:
cfa_sp_offset -= GET_MODE_SIZE (GET_MODE (dest));
pre:
assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset = cfa_sp_offset;
offset = -cfa_sp_offset;
break;
/* With an offset. */
case PLUS:
offset = INTVAL (XEXP (XEXP (dest, 0), 1));
goto off;
case MINUS:
offset = -INTVAL (XEXP (XEXP (dest, 0), 1));
off:
assert (cfa_reg == REGNO (XEXP (XEXP (dest, 0), 0)));
offset -= cfa_offset;
break;
default:
abort ();
}
dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
dwarf2out_reg_save (label, REGNO (src), offset);
break;
default:
abort ();
}
} }
/* Return the size of a Call Frame Instruction. */ /* Return the size of a Call Frame Instruction. */
...@@ -3952,9 +4151,8 @@ output_cfi (cfi, fde) ...@@ -3952,9 +4151,8 @@ output_cfi (cfi, fde)
cfi->dw_cfi_opc cfi->dw_cfi_opc
| (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)); | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
if (flag_verbose_asm) if (flag_verbose_asm)
{ fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
fprintf (asm_out_file, "\t%s DW_CFA_advance_loc", ASM_COMMENT_START); ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
}
fputc ('\n', asm_out_file); fputc ('\n', asm_out_file);
} }
else if (cfi->dw_cfi_opc == DW_CFA_offset) else if (cfi->dw_cfi_opc == DW_CFA_offset)
...@@ -3963,9 +4161,8 @@ output_cfi (cfi, fde) ...@@ -3963,9 +4161,8 @@ output_cfi (cfi, fde)
cfi->dw_cfi_opc cfi->dw_cfi_opc
| (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)); | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
if (flag_verbose_asm) if (flag_verbose_asm)
{ fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
fprintf (asm_out_file, "\t%s DW_CFA_offset", ASM_COMMENT_START); ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
}
fputc ('\n', asm_out_file); fputc ('\n', asm_out_file);
output_uleb128(cfi->dw_cfi_oprnd2.dw_cfi_offset); output_uleb128(cfi->dw_cfi_oprnd2.dw_cfi_offset);
fputc ('\n', asm_out_file); fputc ('\n', asm_out_file);
...@@ -3976,9 +4173,8 @@ output_cfi (cfi, fde) ...@@ -3976,9 +4173,8 @@ output_cfi (cfi, fde)
cfi->dw_cfi_opc cfi->dw_cfi_opc
| (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)); | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
if (flag_verbose_asm) if (flag_verbose_asm)
{ fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
fprintf (asm_out_file, "\t%s DW_CFA_restore", ASM_COMMENT_START); ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
}
fputc ('\n', asm_out_file); fputc ('\n', asm_out_file);
} }
else else
...@@ -5534,12 +5730,54 @@ add_const_value_attribute (die, rtl) ...@@ -5534,12 +5730,54 @@ add_const_value_attribute (die, rtl)
/* Note that a CONST_DOUBLE rtx could represent either an integer or a /* Note that a CONST_DOUBLE rtx could represent either an integer or a
floating-point constant. A CONST_DOUBLE is used whenever the floating-point constant. A CONST_DOUBLE is used whenever the
constant requires more than one word in order to be adequately constant requires more than one word in order to be adequately
represented. In all such cases, the original mode of the constant represented. We output CONST_DOUBLEs as blocks. */
value is preserved as the mode of the CONST_DOUBLE rtx, but for {
simplicity we always just output CONST_DOUBLEs using 8 bytes. */ register enum machine_mode mode = GET_MODE (rtl);
add_AT_double (die, DW_AT_const_value,
(unsigned) CONST_DOUBLE_HIGH (rtl), if (GET_MODE_CLASS (mode) == MODE_FLOAT)
(unsigned) CONST_DOUBLE_LOW (rtl)); {
union real_extract u;
jmp_buf handler;
register unsigned length = GET_MODE_SIZE (mode) / 4;
register long *array = (long *) xmalloc (length * sizeof (long));
bcopy ((char *) &CONST_DOUBLE_LOW (rtl), (char *) &u, sizeof u);
if (setjmp (handler))
{
error ("floating point trap outputting debug info");
u.d = dconst0;
}
set_float_handler (handler);
switch (mode)
{
case SFmode:
REAL_VALUE_TO_TARGET_SINGLE (u.d, array[0]);
break;
case DFmode:
REAL_VALUE_TO_TARGET_DOUBLE (u.d, array);
break;
case XFmode:
case TFmode:
REAL_VALUE_TO_TARGET_LONG_DOUBLE (u.d, array);
break;
default:
abort ();
}
set_float_handler (NULL_PTR);
add_AT_float (die, DW_AT_const_value, length, array);
}
else
add_AT_long_long (die, DW_AT_const_value,
CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
}
break; break;
case CONST_STRING: case CONST_STRING:
...@@ -8043,59 +8281,6 @@ dwarf2out_begin_prologue () ...@@ -8043,59 +8281,6 @@ dwarf2out_begin_prologue ()
fde->dw_fde_cfi = NULL; fde->dw_fde_cfi = NULL;
} }
/* Output a marker (i.e. a label) for the point in the generated code where
the real body of the function begins (after parameters have been moved to
their home locations). */
void
dwarf2out_begin_function ()
{
#ifdef MIPS_DEBUGGING_INFO
char label[MAX_ARTIFICIAL_LABEL_BYTES];
register long int offset;
register dw_fde_ref fde;
register dw_cfi_ref cfi;
register int regno, fp_inc;
function_section (current_function_decl);
ASM_GENERATE_INTERNAL_LABEL (label, BODY_BEGIN_LABEL,
current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
/* Define the CFA as an offset from either the frame pointer
or the stack pointer. */
dwarf2out_def_cfa
(label, gen_rtx (PLUS, VOIDmode,
gen_rtx (REG, VOIDmode,
(frame_pointer_needed ? FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM)),
GEN_INT (current_frame_info.total_size)));
/* Record the locations of the return address and any callee-saved regs. */
offset = current_frame_info.gp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; --regno)
if (current_frame_info.mask & (1<<regno))
{
assert (offset >= 0);
if (regno == 31)
dwarf2out_return_save (label, GEN_INT (offset));
else
dwarf2out_reg_save (label, regno, GEN_INT (offset));
offset -= UNITS_PER_WORD / DWARF_CIE_DATA_ALIGNMENT;
}
fp_inc = (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) ? 1 : 2;
offset = current_frame_info.fp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
for (regno = FP_REG_LAST - 1; regno >= FP_REG_FIRST; regno -= fp_inc)
if (current_frame_info.fmask & (1 << (regno - FP_REG_FIRST)))
{
assert (offset >= 0);
dwarf2out_reg_save (label, regno, GEN_INT (offset));
offset -= (fp_inc * UNITS_PER_FPREG) / DWARF_CIE_DATA_ALIGNMENT;
}
#endif
}
/* Output a marker (i.e. a label) for the absolute end of the generated code /* Output a marker (i.e. a label) for the absolute end of the generated code
for a function definition. This gets called *after* the epilogue code has for a function definition. This gets called *after* the epilogue code has
been generated. */ been generated. */
...@@ -8336,12 +8521,11 @@ dwarf2out_init (asm_out_file, main_input_filename) ...@@ -8336,12 +8521,11 @@ dwarf2out_init (asm_out_file, main_input_filename)
/* Generate the CFA instructions common to all FDE's. Do it now for the /* Generate the CFA instructions common to all FDE's. Do it now for the
sake of lookup_cfa. */ sake of lookup_cfa. */
#ifdef MIPS_DEBUGGING_INFO
/* On entry, the Call Frame Address is in the stack pointer register. */
dwarf2out_def_cfa (NULL, gen_rtx (REG, VOIDmode, STACK_POINTER_REGNUM));
/* Set the RA on entry to be the contents of r31. */ #ifdef INCOMING_RETURN_ADDR_RTX
dwarf2out_return_save (NULL, gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31)); /* On entry, the Canonical Frame Address is at SP+0. */
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, 0);
initial_return_save (INCOMING_RETURN_ADDR_RTX);
#endif #endif
} }
......
...@@ -1208,6 +1208,10 @@ final (first, file, optimize, prescan) ...@@ -1208,6 +1208,10 @@ final (first, file, optimize, prescan)
last_ignored_compare = 0; last_ignored_compare = 0;
new_block = 1; new_block = 1;
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
dwarf2out_frame_debug (NULL_RTX);
#endif
check_exception_handler_labels (); check_exception_handler_labels ();
/* Make a map indicating which line numbers appear in this function. /* Make a map indicating which line numbers appear in this function.
...@@ -1370,12 +1374,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -1370,12 +1374,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (write_symbols == DWARF_DEBUG) if (write_symbols == DWARF_DEBUG)
dwarfout_begin_function (); dwarfout_begin_function ();
#endif #endif
#ifdef DWARF2_DEBUGGING_INFO
/* This outputs a marker where the function body starts, so it
must be after the prologue. */
if (write_symbols == DWARF2_DEBUG)
dwarf2out_begin_function ();
#endif
break; break;
} }
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
...@@ -2104,6 +2102,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -2104,6 +2102,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
output_asm_insn (template, recog_operand); output_asm_insn (template, recog_operand);
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
/* If this insn is part of the prologue, emit DWARF v2
call frame info. */
if (write_symbols == DWARF2_DEBUG && RTX_FRAME_RELATED_P (insn))
dwarf2out_frame_debug (insn);
#endif
#if 0 #if 0
/* It's not at all clear why we did this and doing so interferes /* It's not at all clear why we did this and doing so interferes
with tests we'd like to do to use REG_WAS_0 notes, so let's try with tests we'd like to do to use REG_WAS_0 notes, so let's try
......
...@@ -140,6 +140,10 @@ typedef struct rtx_def ...@@ -140,6 +140,10 @@ typedef struct rtx_def
In a REG, nonzero means this reg refers to the return value In a REG, nonzero means this reg refers to the return value
of the current function. */ of the current function. */
unsigned integrated : 1; unsigned integrated : 1;
/* Nonzero if this rtx is related to the call frame, either changing how
we compute the frame address or saving and restoring registers in
the prologue and epilogue. */
unsigned frame_related : 1;
/* The first element of the operands of this rtx. /* The first element of the operands of this rtx.
The number of operands and their types are controlled The number of operands and their types are controlled
by the `code' field, according to rtl.def. */ by the `code' field, according to rtl.def. */
...@@ -165,6 +169,7 @@ typedef struct rtx_def ...@@ -165,6 +169,7 @@ typedef struct rtx_def
#define RTX_INTEGRATED_P(RTX) ((RTX)->integrated) #define RTX_INTEGRATED_P(RTX) ((RTX)->integrated)
#define RTX_UNCHANGING_P(RTX) ((RTX)->unchanging) #define RTX_UNCHANGING_P(RTX) ((RTX)->unchanging)
#define RTX_FRAME_RELATED_P(RTX) ((RTX)->frame_related)
/* RTL vector. These appear inside RTX's when there is a need /* RTL vector. These appear inside RTX's when there is a need
for a variable number of things. The principle use is inside for a variable number of things. The principle use is inside
......
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