__inline__
#endif
static int
-save_regs (file, low, high, base, offset, n_regs)
+save_regs (file, low, high, base, offset, n_regs, real_offset)
FILE *file;
int low, high;
char *base;
int offset;
int n_regs;
+ int real_offset;
{
int i;
for (i = low; i < high; i++)
{
if (regs_ever_live[i] && ! call_used_regs[i])
- fprintf (file, "\tstx %s,[%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs),
- n_regs += 2;
+ {
+ fprintf (file, "\tstx %s,[%s+%d]\n",
+ reg_names[i], base, offset + 4 * n_regs);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
+#endif
+ n_regs += 2;
+ }
}
}
else
{
if (regs_ever_live[i] && ! call_used_regs[i])
if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tstd %s,[%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs),
- n_regs += 2;
+ {
+ fprintf (file, "\tstd %s,[%s+%d]\n",
+ reg_names[i], base, offset + 4 * n_regs);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+ dwarf2out_reg_save (l, i, real_offset + 4 * n_regs);
+ dwarf2out_reg_save (l, i+1, real_offset + 4 * n_regs + 4);
+ }
+#endif
+ n_regs += 2;
+ }
else
+ {
+ fprintf (file, "\tst %s,[%s+%d]\n",
+ reg_names[i], base, offset + 4 * n_regs);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
+#endif
+ n_regs += 2;
+ }
+ else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
+ {
fprintf (file, "\tst %s,[%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs),
+ reg_names[i+1], base, offset + 4 * n_regs + 4);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
+#endif
n_regs += 2;
- else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tst %s,[%s+%d]\n",
- reg_names[i+1], base, offset + 4 * n_regs + 4),
- n_regs += 2;
+ }
}
}
return n_regs;
}
}
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG && actual_fsize)
+ {
+ char *label = (char *) dwarf2out_cfi_label ();
+
+ /* The canonical frame address refers to the top of the frame. */
+ dwarf2out_def_cfa (label, (leaf_function ? STACK_POINTER_REGNUM
+ : FRAME_POINTER_REGNUM),
+ frame_base_offset);
+
+ if (! leaf_function)
+ {
+ /* Note the register window save. This tells the unwinder that
+ it needs to restore the window registers from the previous
+ frame's window save area at 0(cfa). */
+ dwarf2out_window_save (label);
+
+ /* The return address (-8) is now in %i7. */
+ dwarf2out_return_reg (label, 31);
+ }
+ }
+#endif
+
/* If doing anything with PIC, do it now. */
if (! flag_pic)
fprintf (file, "\t!#PROLOGUE# 1\n");
/* Call saved registers are saved just above the outgoing argument area. */
if (num_gfregs)
{
- int offset, n_regs;
+ int offset, real_offset, n_regs;
char *base;
- offset = -apparent_fsize + frame_base_offset;
+ real_offset = offset = -apparent_fsize + frame_base_offset;
if (offset < -4096 || offset + num_gfregs * 4 > 4096)
{
/* ??? This might be optimized a little as %g1 might already have a
if (TARGET_EPILOGUE && ! leaf_function)
/* ??? Originally saved regs 0-15 here. */
- n_regs = save_regs (file, 0, 8, base, offset, 0);
+ n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
else if (leaf_function)
/* ??? Originally saved regs 0-31 here. */
- n_regs = save_regs (file, 0, 8, base, offset, 0);
+ n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
if (TARGET_EPILOGUE)
- save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
+ save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs,
+ real_offset);
}
leaf_label = 0;
DOUBLEWORD_OP is either "std" for save, "ldd" for restore. */
void
-sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doubleword_op)
+sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doubleword_op, base_offset)
FILE *file;
char *base_reg;
unsigned int offset;
unsigned long fmask;
char *word_op;
char *doubleword_op;
+ unsigned long base_offset;
{
int regno;
offset += UNITS_PER_WORD;
if (word_op[0] == 's')
- fprintf (file, "\t%s %s,[%s+%d]\n",
- doubleword_op, reg_names[regno],
- base_reg, offset);
+ {
+ fprintf (file, "\t%s %s,[%s+%d]\n",
+ doubleword_op, reg_names[regno],
+ base_reg, offset);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+ dwarf2out_reg_save (l, regno, offset + base_offset);
+ dwarf2out_reg_save
+ (l, regno+1, offset+base_offset + UNITS_PER_WORD);
+ }
+#endif
+ }
else
fprintf (file, "\t%s [%s+%d],%s\n",
doubleword_op, base_reg, offset,
else
{
if (word_op[0] == 's')
- fprintf (file, "\t%s %s,[%s+%d]\n",
- word_op, reg_names[regno],
- base_reg, offset);
+ {
+ fprintf (file, "\t%s %s,[%s+%d]\n",
+ word_op, reg_names[regno],
+ base_reg, offset);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_reg_save ("", regno, offset + base_offset);
+#endif
+ }
else
fprintf (file, "\t%s [%s+%d],%s\n",
word_op, base_reg, offset, reg_names[regno]);
if ((fmask & (1L << (regno - 32))) != 0)
{
if (word_op[0] == 's')
- fprintf (file, "\t%s %s,[%s+%d]\n",
- word_op, reg_names[regno],
- base_reg, offset);
+ {
+ fprintf (file, "\t%s %s,[%s+%d]\n",
+ word_op, reg_names[regno],
+ base_reg, offset);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_reg_save ("", regno, offset + base_offset);
+#endif
+ }
else
fprintf (file, "\t%s [%s+%d],%s\n",
word_op, base_reg, offset, reg_names[regno]);
reg_offset += 4;
}
}
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+ if (gmask & FRAME_POINTER_MASK)
+ {
+ dwarf2out_reg_save (l, FRAME_POINTER_REGNUM,
+ reg_offset - 4 - size);
+ dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, 0);
+ }
+ else
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size);
+ }
+#endif
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_return_save ("", reg_offset - size);
+#endif
reg_offset += 4;
}
sparc_flat_save_restore (file, sp_str, reg_offset,
gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
- "st", "std");
+ "st", "std", 0);
}
else
{
offset += 4;
}
}
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+ if (gmask & FRAME_POINTER_MASK)
+ {
+ dwarf2out_reg_save (l, FRAME_POINTER_REGNUM,
+ offset - 4 - size1);
+ dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, 0);
+ }
+ else
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1);
+ }
+#endif
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ /* offset - size1 == reg_offset - size
+ if reg_offset were updated above like offset. */
+ dwarf2out_return_save ("", offset - size1);
+#endif
offset += 4;
}
sparc_flat_save_restore (file, sp_str, offset,
gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
- "st", "std");
+ "st", "std", size - size1);
fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
size - size1, t1_str, sp_str, t1_str, sp_str);
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ if (! (gmask & FRAME_POINTER_MASK))
+ dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
+#endif
}
}
sparc_flat_save_restore (file, sp_str, reg_offset,
current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
- "ld", "ldd");
+ "ld", "ldd", 0);
/* If we had to increment %sp in two steps, record it so the second
restoration in the epilogue finishes up. */
static unsigned long size_of_sleb128 PROTO((long));
static void output_uleb128 PROTO((unsigned long));
static void output_sleb128 PROTO((long));
-static char *dwarf2out_cfi_label PROTO((void));
+char *dwarf2out_cfi_label PROTO((void));
static void add_fde_cfi PROTO((char *, dw_cfi_ref));
static void lookup_cfa_1 PROTO((dw_cfi_ref, unsigned long *,
long *));
almost all svr4 assemblers, except for the sparc, where the section name
must be enclosed in double quotes. (See sparcv4.h). */
#ifndef SECTION_FORMAT
-#define SECTION_FORMAT "\t%s\t%s\n"
+#ifdef PUSHSECTION_FORMAT
+#define SECTION_FORMAT PUSHSECTION_FORMAT
+#else
+#define SECTION_FORMAT "\t%s\t%s\n"
+#endif
#endif
#ifndef FRAME_SECTION
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
+
+ /* GNU extensions */
+ case DW_CFA_GNU_window_save:
+ return "DW_CFA_GNU_window_save";
+
default:
return "DW_CFA_<unknown>";
}
/* Generate a new label for the CFI info to refer to. */
-static char *
+char *
dwarf2out_cfi_label ()
{
static char label[20];
add_fde_cfi (label, cfi);
}
-/* Entry point for saving a register. REG is the GCC register number.
- LABEL and OFFSET are passed to reg_save. */
+/* Add the CFI for saving a register window. LABEL is passed to reg_save.
+ This CFI tells the unwinder that it needs to restore the window registers
+ from the previous frame's window save area.
+
+ ??? Perhaps we should note in the CIE where windows are saved (instead of
+ assuming 0(cfa)) and what registers are in the window. */
+
+void
+dwarf2out_window_save (label)
+ register char * label;
+{
+ register dw_cfi_ref cfi = new_cfi ();
+ cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+ add_fde_cfi (label, cfi);
+}
+
+/* Entry point for saving a register to the stack. REG is the GCC register
+ number. LABEL and OFFSET are passed to reg_save. */
void
dwarf2out_reg_save (label, reg, offset)
reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
}
+/* Entry point for saving the return address in the stack.
+ LABEL and OFFSET are passed to reg_save. */
+
+void
+dwarf2out_return_save (label, offset)
+ register char * label;
+ register long offset;
+{
+ reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset);
+}
+
+/* Entry point for saving the return address in a register.
+ LABEL and SREG are passed to reg_save. */
+
+void
+dwarf2out_return_reg (label, sreg)
+ register char * label;
+ register unsigned sreg;
+{
+ reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0);
+}
+
/* Record the initial position of the return address. RTL is
INCOMING_RETURN_ADDR_RTX. */
abort ();
}
break;
+ case PLUS:
+ /* The return address is at some offset from any value we can
+ actually load. For instance, on the SPARC it is in %i7+8. Just
+ ignore the offset for now; it doesn't matter for unwinding frames. */
+ assert (GET_CODE (XEXP (rtl, 1)) == CONST_INT);
+ initial_return_save (XEXP (rtl, 0));
+ return;
default:
abort ();
}
output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
fputc ('\n', asm_out_file);
break;
+ case DW_CFA_GNU_window_save:
+ break;
default:
break;
}
static unsigned lookup_filename PROTO((char *));
/* Section names used to hold DWARF debugging information. */
-#ifndef DEBUG_SECTION
-#define DEBUG_SECTION ".debug_info"
+#ifndef DEBUG_INFO_SECTION
+#define DEBUG_INFO_SECTION ".debug_info"
#endif
#ifndef ABBREV_SECTION
#define ABBREV_SECTION ".debug_abbrev"
#ifndef DW_MACINFO_SECTION
#define DW_MACINFO_SECTION ".debug_macinfo"
#endif
-#ifndef LINE_SECTION
-#define LINE_SECTION ".debug_line"
+#ifndef DEBUG_LINE_SECTION
+#define DEBUG_LINE_SECTION ".debug_line"
#endif
#ifndef LOC_SECTION
#define LOC_SECTION ".debug_loc"
fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
ASM_COMMENT_START);
fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
ASM_COMMENT_START);
if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
{
fputc ('\n', asm_out_file);
- ASM_OUTPUT_SECTION (asm_out_file, LINE_SECTION);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
output_line_info ();
/* We can only use the low/high_pc attributes if all of the code
add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
}
- add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, LINE_SECTION);
+ add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, DEBUG_LINE_SECTION);
}
/* Output the abbreviation table. */
/* Output debugging information. */
fputc ('\n', asm_out_file);
- ASM_OUTPUT_SECTION (asm_out_file, DEBUG_SECTION);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
output_compilation_unit_header ();
output_die (comp_unit_die);