aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <merrill@gnu.org>1996-12-13 01:31:47 +0000
committerJason Merrill <merrill@gnu.org>1996-12-13 01:31:47 +0000
commit469ac9939bb1bec320f7b3814de1f62423ea219a (patch)
tree16aaf051fd2c4b487fff6c48e868df681f121018 /gcc
parent97adc6ed4cac5b3e857ea1d8166972021ceb772f (diff)
downloadgcc-469ac9939bb1bec320f7b3814de1f62423ea219a.zip
gcc-469ac9939bb1bec320f7b3814de1f62423ea219a.tar.gz
gcc-469ac9939bb1bec320f7b3814de1f62423ea219a.tar.bz2
x
From-SVN: r13305
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.c30
-rw-r--r--gcc/config/i386/i386.h7
-rw-r--r--gcc/config/mips/mips.c43
-rw-r--r--gcc/config/mips/mips.h7
-rw-r--r--gcc/dwarf2out.c500
-rw-r--r--gcc/final.c17
-rw-r--r--gcc/rtl.h5
7 files changed, 395 insertions, 214 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d0b3ac0..d9edb71 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 241650f..ac08c45 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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. */
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index c3a3b2d..cacbf1f 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -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)
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index f1b4d05..9b430ab 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -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 { \
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index dd8276c..99007b3 100644
--- a/gcc/dwarf2out.c
+++ b/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, &reg, &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 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;
{
- 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.
- LABEL and RTL are passed to reg_save. */
+/* 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_return_save (label, rtl)
- register char * label;
- register rtx rtl;
+dwarf2out_frame_debug (insn)
+ rtx insn;
{
- 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. */
@@ -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
}
diff --git a/gcc/final.c b/gcc/final.c
index 40a0911..cc5bedf 100644
--- a/gcc/final.c
+++ b/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.
@@ -1370,12 +1374,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
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;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
@@ -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
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 733f881..83e3cc0 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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