mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-29 02:34:45 +08:00
x
From-SVN: r13305
This commit is contained in:
parent
97adc6ed4c
commit
469ac9939b
@ -1832,6 +1832,7 @@ ix86_expand_prologue ()
|
||||
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|
||||
|| current_function_uses_const_pool);
|
||||
long tsize = get_frame_size ();
|
||||
rtx insn;
|
||||
|
||||
if (!TARGET_SCHEDULE_PROLOGUE)
|
||||
return;
|
||||
@ -1841,17 +1842,23 @@ ix86_expand_prologue ()
|
||||
xops[2] = GEN_INT (tsize);
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
emit_insn (gen_rtx (SET, 0,
|
||||
gen_rtx (MEM, SImode,
|
||||
gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
|
||||
frame_pointer_rtx));
|
||||
emit_move_insn (xops[1], xops[0]);
|
||||
insn = emit_insn
|
||||
(gen_rtx (SET, 0,
|
||||
gen_rtx (MEM, SImode,
|
||||
gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
|
||||
frame_pointer_rtx));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_move_insn (xops[1], xops[0]);
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
if (tsize == 0)
|
||||
;
|
||||
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
|
||||
{
|
||||
xops[3] = gen_rtx (REG, SImode, 0);
|
||||
@ -1877,10 +1884,13 @@ ix86_expand_prologue ()
|
||||
|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
|
||||
{
|
||||
xops[0] = gen_rtx (REG, SImode, regno);
|
||||
emit_insn (gen_rtx (SET, 0,
|
||||
gen_rtx (MEM, SImode,
|
||||
gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
|
||||
xops[0]));
|
||||
insn = emit_insn
|
||||
(gen_rtx (SET, 0,
|
||||
gen_rtx (MEM, SImode,
|
||||
gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
|
||||
xops[0]));
|
||||
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
|
||||
|
@ -2331,6 +2331,13 @@ number as al, and ax.
|
||||
(n) == 7 ? 5 : \
|
||||
(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,
|
||||
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)
|
||||
if (store_p)
|
||||
{
|
||||
rtx insn = emit_move_insn (mem_rtx, reg_rtx);
|
||||
|
||||
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));
|
||||
}
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else if (!TARGET_ABICALLS || mips_abi != ABI_32
|
||||
|| regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
|
||||
@ -5199,17 +5184,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
|
||||
if (store_p)
|
||||
{
|
||||
rtx insn = emit_move_insn (mem_rtx, reg_rtx);
|
||||
|
||||
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));
|
||||
}
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
emit_move_insn (reg_rtx, mem_rtx);
|
||||
@ -5452,12 +5427,7 @@ mips_expand_prologue ()
|
||||
insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
tsize_rtx));
|
||||
|
||||
if (write_symbols == DWARF2_DEBUG)
|
||||
REG_NOTES (insn)
|
||||
= gen_rtx (EXPR_LIST, REG_FRAME,
|
||||
gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
|
||||
GEN_INT (tsize)),
|
||||
REG_NOTES (insn));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0);
|
||||
@ -5471,12 +5441,7 @@ mips_expand_prologue ()
|
||||
else
|
||||
insn= emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
|
||||
|
||||
if (write_symbols == DWARF2_DEBUG)
|
||||
REG_NOTES (insn)
|
||||
= gen_rtx (EXPR_LIST, REG_FRAME,
|
||||
gen_rtx (PLUS, VOIDmode, frame_pointer_rtx,
|
||||
GEN_INT (tsize)),
|
||||
REG_NOTES (insn));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
if (TARGET_ABICALLS && mips_abi != ABI_32)
|
||||
|
@ -927,11 +927,16 @@ while (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
|
||||
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. */
|
||||
#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. */
|
||||
#define PUT_SDB_SCL(a) \
|
||||
do { \
|
||||
|
502
gcc/dwarf2out.c
502
gcc/dwarf2out.c
@ -2,6 +2,7 @@
|
||||
Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
Contributed by Gary Funck (gary@intrepid.com). Derived from the
|
||||
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.
|
||||
|
||||
@ -23,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifdef DWARF2_DEBUGGING_INFO
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include "dwarf2.h"
|
||||
#include "tree.h"
|
||||
#include "flags.h"
|
||||
@ -67,7 +69,8 @@ typedef enum
|
||||
dw_val_class_loc,
|
||||
dw_val_class_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_die_ref,
|
||||
dw_val_class_fde_ref,
|
||||
@ -95,12 +98,20 @@ typedef struct pubname_struct *pubname_ref;
|
||||
typedef dw_die_ref *arange_ref;
|
||||
|
||||
/* 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 dw_dbl_low;
|
||||
unsigned long hi;
|
||||
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
|
||||
line nuber associated with the label generated for that
|
||||
@ -134,7 +145,8 @@ typedef struct dw_val_struct
|
||||
dw_loc_descr_ref val_loc;
|
||||
long int val_int;
|
||||
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;
|
||||
unsigned val_fde_index;
|
||||
char *val_str;
|
||||
@ -301,7 +313,11 @@ extern char *language_string;
|
||||
static unsigned cie_size;
|
||||
|
||||
/* 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. */
|
||||
#define DWARF_FDE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2 * PTR_SIZE)
|
||||
@ -830,9 +846,9 @@ char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
#define DWARF_FRAME_REGNUM(REG) (DBX_REGISTER_NUMBER (REG) + 1)
|
||||
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
|
||||
#endif
|
||||
|
||||
/************************ general utility functions **************************/
|
||||
@ -1948,7 +1964,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
|
||||
|
||||
/* Add an unsigned double integer attribute value to a DIE. */
|
||||
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 enum dwarf_attribute attr_kind;
|
||||
register unsigned long val_hi;
|
||||
@ -1959,9 +1975,29 @@ add_AT_double (die, attr_kind, val_hi, val_low)
|
||||
{
|
||||
attr->dw_attr_next = NULL;
|
||||
attr->dw_attr = attr_kind;
|
||||
attr->dw_attr_val.val_class = dw_val_class_double_const;
|
||||
attr->dw_attr_val.v.val_dbl_const.dw_dbl_hi = val_hi;
|
||||
attr->dw_attr_val.v.val_dbl_const.dw_dbl_low = val_low;
|
||||
attr->dw_attr_val.val_class = dw_val_class_long_long;
|
||||
attr->dw_attr_val.v.val_long_long.hi = val_hi;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -2502,10 +2538,13 @@ print_die (die, outfile)
|
||||
case dw_val_class_unsigned_const:
|
||||
fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned);
|
||||
break;
|
||||
case dw_val_class_double_const:
|
||||
case dw_val_class_long_long:
|
||||
fprintf (outfile, "constant (%u,%u)",
|
||||
a->dw_attr_val.v.val_dbl_const.dw_dbl_hi,
|
||||
a->dw_attr_val.v.val_dbl_const.dw_dbl_low);
|
||||
a->dw_attr_val.v.val_long_long.hi,
|
||||
a->dw_attr_val.v.val_long_long.low);
|
||||
break;
|
||||
case dw_val_class_float:
|
||||
fprintf (outfile, "floating-point constant");
|
||||
break;
|
||||
case dw_val_class_flag:
|
||||
fprintf (outfile, "%u", a->dw_attr_val.v.val_flag);
|
||||
@ -2909,8 +2948,11 @@ size_of_die (die)
|
||||
case dw_val_class_unsigned_const:
|
||||
size += constant_size (a->dw_attr_val.v.val_unsigned);
|
||||
break;
|
||||
case dw_val_class_double_const:
|
||||
size += 8;
|
||||
case dw_val_class_long_long:
|
||||
size += 1 + 8; /* block */
|
||||
break;
|
||||
case dw_val_class_float:
|
||||
size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */
|
||||
break;
|
||||
case dw_val_class_flag:
|
||||
size += 1;
|
||||
@ -3237,8 +3279,10 @@ value_format (v)
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
case dw_val_class_double_const:
|
||||
return DW_FORM_data8;
|
||||
case dw_val_class_long_long:
|
||||
return DW_FORM_block1;
|
||||
case dw_val_class_float:
|
||||
return DW_FORM_block1;
|
||||
case dw_val_class_flag:
|
||||
return DW_FORM_flag;
|
||||
case dw_val_class_die_ref:
|
||||
@ -3342,9 +3386,7 @@ output_loc_operands (loc)
|
||||
break;
|
||||
case DW_OP_const8u:
|
||||
case DW_OP_const8s:
|
||||
ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
|
||||
val1->v.val_dbl_const.dw_dbl_hi,
|
||||
val2->v.val_dbl_const.dw_dbl_low);
|
||||
abort ();
|
||||
fputc ('\n', asm_out_file);
|
||||
break;
|
||||
case DW_OP_constu:
|
||||
@ -3459,6 +3501,8 @@ output_die (die)
|
||||
register unsigned long ref_offset;
|
||||
register unsigned long size;
|
||||
register dw_loc_descr_ref loc;
|
||||
register int i;
|
||||
|
||||
output_uleb128 (die->die_abbrev);
|
||||
if (flag_verbose_asm)
|
||||
fprintf (asm_out_file, " (DIE (0x%x) %s)",
|
||||
@ -3530,10 +3574,36 @@ output_die (die)
|
||||
abort ();
|
||||
}
|
||||
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,
|
||||
a->dw_attr_val.v.val_dbl_const.dw_dbl_hi,
|
||||
a->dw_attr_val.v.val_dbl_const.dw_dbl_low);
|
||||
a->dw_attr_val.v.val_long_long.hi,
|
||||
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;
|
||||
case dw_val_class_flag:
|
||||
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
|
||||
@ -3571,7 +3641,9 @@ output_die (die)
|
||||
default:
|
||||
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)
|
||||
{
|
||||
@ -3631,35 +3703,23 @@ output_compilation_unit_header ()
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
|
||||
/* Extract the register and offset values from RTL. If no register number
|
||||
is specified, return -1 to indicate frame-relative addressing. */
|
||||
static void
|
||||
decode_cfi_rtl (rtl, regp, offsetp)
|
||||
register rtx rtl;
|
||||
register unsigned long *regp;
|
||||
register long *offsetp;
|
||||
/* Generate a new label for the CFI info to refer to. */
|
||||
|
||||
char *
|
||||
dwarf2out_cfi_label ()
|
||||
{
|
||||
switch (GET_CODE (rtl))
|
||||
{
|
||||
case REG:
|
||||
*regp = reg_number (rtl);
|
||||
*offsetp = 0;
|
||||
break;
|
||||
case PLUS:
|
||||
*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 ();
|
||||
}
|
||||
static char label[20];
|
||||
static unsigned long label_num = 0;
|
||||
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++);
|
||||
ASM_OUTPUT_LABEL (asm_out_file, label);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
|
||||
or to the CIE if LABEL is NULL. */
|
||||
|
||||
static void
|
||||
add_fde_cfi (label, cfi)
|
||||
register char * label;
|
||||
@ -3668,6 +3728,8 @@ add_fde_cfi (label, cfi)
|
||||
if (label)
|
||||
{
|
||||
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
|
||||
|| strcmp (label, fde->dw_fde_current_label) != 0)
|
||||
{
|
||||
@ -3730,20 +3792,20 @@ lookup_cfa (regp, offsetp)
|
||||
}
|
||||
|
||||
/* 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
|
||||
dwarf2out_def_cfa (label, rtl)
|
||||
dwarf2out_def_cfa (label, reg, offset)
|
||||
register char * label;
|
||||
register rtx rtl;
|
||||
register unsigned reg;
|
||||
register long offset;
|
||||
{
|
||||
register dw_cfi_ref cfi;
|
||||
unsigned long reg, old_reg;
|
||||
long offset, old_offset;
|
||||
unsigned old_reg;
|
||||
long old_offset;
|
||||
|
||||
decode_cfi_rtl (rtl, ®, &offset);
|
||||
reg = DWARF_FRAME_REGNUM (reg);
|
||||
lookup_cfa (&old_reg, &old_offset);
|
||||
|
||||
if (reg == old_reg && offset == old_offset)
|
||||
@ -3775,29 +3837,21 @@ dwarf2out_def_cfa (label, rtl)
|
||||
|
||||
/* Add the CFI for saving a register. REG is the CFA column number.
|
||||
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
|
||||
reg_save (label, reg, rtl)
|
||||
reg_save (label, reg, sreg, offset)
|
||||
register char * label;
|
||||
register unsigned long reg;
|
||||
register rtx rtl;
|
||||
register unsigned reg;
|
||||
register unsigned sreg;
|
||||
register long offset;
|
||||
{
|
||||
register dw_cfi_ref cfi;
|
||||
unsigned long sreg;
|
||||
long offset;
|
||||
|
||||
cfi = new_cfi ();
|
||||
register dw_cfi_ref cfi = new_cfi ();
|
||||
|
||||
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
|
||||
|
||||
decode_cfi_rtl (rtl, &sreg, &offset);
|
||||
offset /= DWARF_CIE_DATA_ALIGNMENT;
|
||||
|
||||
if (sreg == (unsigned long) -1)
|
||||
if (sreg == -1)
|
||||
{
|
||||
if (reg & ~0x3f)
|
||||
/* The register number won't fit in 6 bits, so we have to use
|
||||
@ -3805,6 +3859,9 @@ reg_save (label, reg, rtl)
|
||||
cfi->dw_cfi_opc = DW_CFA_offset_extended;
|
||||
else
|
||||
cfi->dw_cfi_opc = DW_CFA_offset;
|
||||
|
||||
offset /= DWARF_CIE_DATA_ALIGNMENT;
|
||||
assert (offset >= 0);
|
||||
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
|
||||
}
|
||||
else
|
||||
@ -3817,24 +3874,166 @@ reg_save (label, reg, rtl)
|
||||
}
|
||||
|
||||
/* 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
|
||||
dwarf2out_reg_save (label, reg, rtl)
|
||||
dwarf2out_reg_save (label, reg, offset)
|
||||
register char * label;
|
||||
register unsigned long reg;
|
||||
register rtx rtl;
|
||||
register unsigned reg;
|
||||
register long offset;
|
||||
{
|
||||
reg_save (label, DWARF_FRAME_REGNUM (reg), rtl);
|
||||
reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
|
||||
}
|
||||
|
||||
/* Entry point for saving the return address.
|
||||
LABEL and RTL are passed to reg_save. */
|
||||
void
|
||||
dwarf2out_return_save (label, rtl)
|
||||
register char * label;
|
||||
/* Record the initial position of the return address. RTL is
|
||||
INCOMING_RETURN_ADDR_RTX. */
|
||||
|
||||
static void
|
||||
initial_return_save (rtl)
|
||||
register rtx rtl;
|
||||
{
|
||||
reg_save (label, DWARF_FRAME_RETURN_COLUMN, 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);
|
||||
}
|
||||
|
||||
/* Record call frame debugging information for INSN, which either
|
||||
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
|
||||
dwarf2out_frame_debug (insn)
|
||||
rtx insn;
|
||||
{
|
||||
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. */
|
||||
@ -3952,9 +4151,8 @@ output_cfi (cfi, fde)
|
||||
cfi->dw_cfi_opc
|
||||
| (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
|
||||
if (flag_verbose_asm)
|
||||
{
|
||||
fprintf (asm_out_file, "\t%s DW_CFA_advance_loc", ASM_COMMENT_START);
|
||||
}
|
||||
fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
|
||||
ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
else if (cfi->dw_cfi_opc == DW_CFA_offset)
|
||||
@ -3963,9 +4161,8 @@ output_cfi (cfi, fde)
|
||||
cfi->dw_cfi_opc
|
||||
| (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
|
||||
if (flag_verbose_asm)
|
||||
{
|
||||
fprintf (asm_out_file, "\t%s DW_CFA_offset", ASM_COMMENT_START);
|
||||
}
|
||||
fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
|
||||
ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
|
||||
fputc ('\n', asm_out_file);
|
||||
output_uleb128(cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
||||
fputc ('\n', asm_out_file);
|
||||
@ -3976,9 +4173,8 @@ output_cfi (cfi, fde)
|
||||
cfi->dw_cfi_opc
|
||||
| (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
|
||||
if (flag_verbose_asm)
|
||||
{
|
||||
fprintf (asm_out_file, "\t%s DW_CFA_restore", ASM_COMMENT_START);
|
||||
}
|
||||
fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
|
||||
ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
else
|
||||
@ -5534,12 +5730,54 @@ add_const_value_attribute (die, rtl)
|
||||
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
|
||||
floating-point constant. A CONST_DOUBLE is used whenever the
|
||||
constant requires more than one word in order to be adequately
|
||||
represented. In all such cases, the original mode of the constant
|
||||
value is preserved as the mode of the CONST_DOUBLE rtx, but for
|
||||
simplicity we always just output CONST_DOUBLEs using 8 bytes. */
|
||||
add_AT_double (die, DW_AT_const_value,
|
||||
(unsigned) CONST_DOUBLE_HIGH (rtl),
|
||||
(unsigned) CONST_DOUBLE_LOW (rtl));
|
||||
represented. We output CONST_DOUBLEs as blocks. */
|
||||
{
|
||||
register enum machine_mode mode = GET_MODE (rtl);
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
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;
|
||||
|
||||
case CONST_STRING:
|
||||
@ -8043,59 +8281,6 @@ dwarf2out_begin_prologue ()
|
||||
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
|
||||
for a function definition. This gets called *after* the epilogue code has
|
||||
been generated. */
|
||||
@ -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
|
||||
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. */
|
||||
dwarf2out_return_save (NULL, gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31));
|
||||
#ifdef INCOMING_RETURN_ADDR_RTX
|
||||
/* 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
|
||||
}
|
||||
|
||||
|
17
gcc/final.c
17
gcc/final.c
@ -1208,6 +1208,10 @@ final (first, file, optimize, prescan)
|
||||
last_ignored_compare = 0;
|
||||
new_block = 1;
|
||||
|
||||
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
|
||||
dwarf2out_frame_debug (NULL_RTX);
|
||||
#endif
|
||||
|
||||
check_exception_handler_labels ();
|
||||
|
||||
/* Make a map indicating which line numbers appear in this function.
|
||||
@ -1369,12 +1373,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
|
||||
must be after the prologue. */
|
||||
if (write_symbols == DWARF_DEBUG)
|
||||
dwarfout_begin_function ();
|
||||
#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;
|
||||
}
|
||||
@ -2104,6 +2102,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
|
||||
|
||||
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
|
||||
/* 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
|
||||
|
@ -140,6 +140,10 @@ typedef struct rtx_def
|
||||
In a REG, nonzero means this reg refers to the return value
|
||||
of the current function. */
|
||||
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 number of operands and their types are controlled
|
||||
by the `code' field, according to rtl.def. */
|
||||
@ -165,6 +169,7 @@ typedef struct rtx_def
|
||||
|
||||
#define RTX_INTEGRATED_P(RTX) ((RTX)->integrated)
|
||||
#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
|
||||
for a variable number of things. The principle use is inside
|
||||
|
Loading…
Reference in New Issue
Block a user