diff options
author | Jason Merrill <merrill@gnu.org> | 1996-12-13 01:31:47 +0000 |
---|---|---|
committer | Jason Merrill <merrill@gnu.org> | 1996-12-13 01:31:47 +0000 |
commit | 469ac9939bb1bec320f7b3814de1f62423ea219a (patch) | |
tree | 16aaf051fd2c4b487fff6c48e868df681f121018 /gcc | |
parent | 97adc6ed4cac5b3e857ea1d8166972021ceb772f (diff) | |
download | gcc-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.c | 30 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 7 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 43 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 7 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 500 | ||||
-rw-r--r-- | gcc/final.c | 17 | ||||
-rw-r--r-- | gcc/rtl.h | 5 |
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, ®, &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 @@ -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 |