Commit a6ab3aad by Jason Merrill

x

From-SVN: r14390
parent 991d6599
......@@ -2363,6 +2363,9 @@ number as al, and ax.
/* PC is dbx register 8; let's use that column for RA. */
#define DWARF_FRAME_RETURN_COLUMN 8
/* Before the prologue, the top of the frame is at 4(%esp). */
#define INCOMING_FRAME_SP_OFFSET 4
/* 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. */
......
......@@ -133,3 +133,9 @@ do { fprintf (FILE, "\t%s\t", ASM_LONG); \
#define SUPPORTS_WEAK 0
#endif
#endif
/* If we have a definition of INCOMING_RETURN_ADDR_RTX, assume that
the rest of the DWARF 2 frame unwind support is also provided. */
#ifdef INCOMING_RETURN_ADDR_RTX
#define DWARF2_UNWIND_INFO
#endif
......@@ -21,6 +21,7 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "defaults.h"
/* The first part of this file deals with the DWARF 2 frame unwind
information, which is also used by the GCC efficient exception handling
......@@ -28,7 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
information. */
#if defined (DWARF2_DEBUGGING_INFO) || defined (INCOMING_RETURN_ADDR_RTX)
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
#include <stdio.h>
#include <setjmp.h>
......@@ -41,7 +42,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "insn-config.h"
#include "reload.h"
#include "output.h"
#include "defaults.h"
#include "expr.h"
#include "except.h"
......@@ -91,7 +91,6 @@ dw_cfi_node;
typedef struct dw_fde_struct
{
unsigned long dw_fde_offset;
char *dw_fde_begin;
char *dw_fde_current_label;
char *dw_fde_end;
......@@ -128,13 +127,6 @@ dw_fde_node;
#define DWARF_ROUND(SIZE,BOUNDARY) \
(((SIZE) + (BOUNDARY) - 1) & ~((BOUNDARY) - 1))
/* Fixed size portion of the CIE (including the length field). */
#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5)
/* The un-padded size of the CIE. Initialized in calc_fde_sizes, used
in output_call_frame_info. */
static unsigned cie_size;
/* Offsets recorded in opcodes are a multiple of this alignment factor. */
#ifdef STACK_GROWS_DOWNWARD
#define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_WORD)
......@@ -142,13 +134,6 @@ static unsigned cie_size;
#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)
/* This location is used by calc_fde_sizes() to keep track
the offset of each FDE within the .debug_frame section. */
static unsigned long next_fde_offset;
/* A pointer to the base of a table that contains frame description
information for each routine. */
static dw_fde_ref fde_table;
......@@ -197,9 +182,6 @@ static void lookup_cfa PROTO((unsigned long *, long *));
static void reg_save PROTO((char *, unsigned, unsigned,
long));
static void initial_return_save PROTO((rtx));
static unsigned long size_of_cfi PROTO((dw_cfi_ref));
static unsigned long size_of_fde PROTO((dw_fde_ref, unsigned long *));
static void calc_fde_sizes PROTO((void));
static void output_cfi PROTO((dw_cfi_ref, dw_fde_ref));
static void output_call_frame_info PROTO((int));
static unsigned reg_number PROTO((rtx));
......@@ -266,6 +248,10 @@ static unsigned reg_number PROTO((rtx));
#ifndef FUNC_END_LABEL
#define FUNC_END_LABEL "LFE"
#endif
#define CIE_AFTER_SIZE_LABEL "LSCIE"
#define CIE_END_LABEL "LECIE"
#define FDE_AFTER_SIZE_LABEL "LSFDE"
#define FDE_END_LABEL "LEFDE"
/* Definitions of defaults for various types of primitive assembly language
output operations. These may be overridden from within the tm.h file,
......@@ -374,6 +360,33 @@ static unsigned reg_number PROTO((rtx));
} while (0)
#endif
/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
newline is produced. When flag_verbose_asm is asserted, we add commnetary
at the end of the line, so we must avoid output of a newline here. */
#ifndef ASM_OUTPUT_DWARF_STRING
#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
do { \
register int slen = strlen(P); \
register char *p = (P); \
register int i; \
fprintf (FILE, "\t.ascii \""); \
for (i = 0; i < slen; i++) \
{ \
register int c = p[i]; \
if (c == '\"' || c == '\\') \
putc ('\\', FILE); \
if (c >= ' ' && c < 0177) \
putc (c, FILE); \
else \
{ \
fprintf (FILE, "\\%o", c); \
} \
} \
fprintf (FILE, "\\0\""); \
} \
while (0)
#endif
/* The DWARF 2 CFA column which tracks the return address. Normally this
is the column for PC, or the first column after all of the hard
registers. */
......@@ -391,6 +404,12 @@ static unsigned reg_number PROTO((rtx));
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif
/* The offset from the incoming value of %sp to the top of the stack frame
for the current function. */
#ifndef INCOMING_FRAME_SP_OFFSET
#define INCOMING_FRAME_SP_OFFSET 0
#endif
/* Return a pointer to a copy of the section string name S with all
attributes stripped off. */
......@@ -611,7 +630,7 @@ lookup_cfa (regp, offsetp)
}
/* The current rule for calculating the DWARF2 canonical frame address. */
static unsigned cfa_reg;
static unsigned long cfa_reg;
static long cfa_offset;
/* The register used for saving registers to the stack, and its offset
......@@ -806,7 +825,7 @@ initial_return_save (rtl)
abort ();
}
reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset);
reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset);
}
/* Record call frame debugging information for INSN, which either
......@@ -828,10 +847,11 @@ dwarf2out_frame_debug (insn)
if (insn == NULL_RTX)
{
/* Set up state for generating call frame debug info. */
lookup_cfa (&cfa_reg, &cfa_offset);
assert (cfa_reg == DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
cfa_reg = STACK_POINTER_REGNUM;
cfa_offset = 0;
cfa_store_reg = STACK_POINTER_REGNUM;
cfa_store_offset = 0;
cfa_store_reg = cfa_reg;
cfa_store_offset = cfa_offset;
cfa_temp_reg = -1;
cfa_temp_value = 0;
return;
......@@ -1005,114 +1025,6 @@ size_of_sleb128 (value)
return size;
}
/* Return the size of a Call Frame Instruction. */
static unsigned long
size_of_cfi (cfi)
dw_cfi_ref cfi;
{
register unsigned long size;
/* Count the 1-byte opcode */
size = 1;
switch (cfi->dw_cfi_opc)
{
case DW_CFA_offset:
size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
break;
case DW_CFA_set_loc:
size += PTR_SIZE;
break;
case DW_CFA_advance_loc1:
size += 1;
break;
case DW_CFA_advance_loc2:
size += 2;
break;
case DW_CFA_advance_loc4:
size += 4;
break;
#ifdef MIPS_DEBUGGING_INFO
case DW_CFA_MIPS_advance_loc8:
size += 8;
break;
#endif
case DW_CFA_offset_extended:
case DW_CFA_def_cfa:
size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
break;
case DW_CFA_restore_extended:
case DW_CFA_undefined:
size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
break;
case DW_CFA_same_value:
case DW_CFA_def_cfa_register:
size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
break;
case DW_CFA_register:
size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
break;
case DW_CFA_def_cfa_offset:
size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
break;
default:
break;
}
return size;
}
/* Return the size of an FDE sans the length word. */
static inline unsigned long
size_of_fde (fde, npad)
dw_fde_ref fde;
unsigned long *npad;
{
register dw_cfi_ref cfi;
register unsigned long aligned_size;
register unsigned long size;
size = DWARF_FDE_HEADER_SIZE;
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
size += size_of_cfi(cfi);
/* Round the size up to a word boundary. */
aligned_size = DWARF_ROUND (size, PTR_SIZE);
*npad = aligned_size - size;
return aligned_size;
}
/* Calculate the size of the FDE table, and establish the offset
of each FDE in the .debug_frame section. */
static void
calc_fde_sizes ()
{
register unsigned long i;
register dw_fde_ref fde;
register unsigned long fde_size;
register dw_cfi_ref cfi;
unsigned long fde_pad;
cie_size = DWARF_CIE_HEADER_SIZE;
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
cie_size += size_of_cfi (cfi);
/* Initialize the beginning FDE offset. */
next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
for (i = 0; i < fde_table_in_use; ++i)
{
fde = &fde_table[i];
fde->dw_fde_offset = next_fde_offset;
fde_size = size_of_fde (fde, &fde_pad);
next_fde_offset += fde_size;
}
}
/* Output an unsigned LEB128 quantity. */
static void
......@@ -1299,6 +1211,10 @@ output_call_frame_info (for_eh)
register unsigned long fde_size;
register dw_cfi_ref cfi;
unsigned long fde_pad;
char l1[20], l2[20];
/* Do we want to include a pointer to the exception table? */
int eh_ptr = for_eh && exception_table_p ();
/* Only output the info if it will be interesting. */
for (i = 0; i < fde_table_in_use; ++i)
......@@ -1307,9 +1223,6 @@ output_call_frame_info (for_eh)
if (i == fde_table_in_use)
return;
/* (re-)initialize the beginning FDE offset. */
next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
fputc ('\n', asm_out_file);
if (for_eh)
{
......@@ -1324,12 +1237,16 @@ output_call_frame_info (for_eh)
ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
/* Output the CIE. */
ASM_OUTPUT_DWARF_DATA (asm_out_file, next_fde_offset - DWARF_OFFSET_SIZE);
ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s Length of Common Information Entry",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
ASM_OUTPUT_LABEL (asm_out_file, l1);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE Identifier Tag", ASM_COMMENT_START);
......@@ -1346,9 +1263,21 @@ output_call_frame_info (for_eh)
fprintf (asm_out_file, "\t%s CIE Version", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE Augmentation (none)", ASM_COMMENT_START);
if (eh_ptr)
{
/* The "z" augmentation was defined by SGI; the FDE contains a pointer
to the exception region info for the frame. */
ASM_OUTPUT_DWARF_STRING (asm_out_file, "z");
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START);
}
else
{
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE Augmentation (none)",
ASM_COMMENT_START);
}
fputc ('\n', asm_out_file);
output_uleb128 (1);
......@@ -1366,20 +1295,21 @@ output_call_frame_info (for_eh)
fprintf (asm_out_file, "\t%s CIE RA Column", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
if (eh_ptr)
{
output_uleb128 (0);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE augmentation fields length",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
output_cfi (cfi, NULL);
/* Pad the CIE out to an address sized boundary. */
for (i = next_fde_offset - cie_size; i; --i)
{
/* Pad out to a pointer size boundary */
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
ASM_OUTPUT_LABEL (asm_out_file, l2);
/* Loop through all of the FDE's. */
for (i = 0; i < fde_table_in_use; ++i)
......@@ -1388,12 +1318,14 @@ output_call_frame_info (for_eh)
if (fde->dw_fde_cfi == NULL)
continue;
fde_size = size_of_fde (fde, &fde_pad);
ASM_OUTPUT_DWARF_DATA (asm_out_file, fde_size - DWARF_OFFSET_SIZE);
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i*2);
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i*2);
ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s FDE Length", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
ASM_OUTPUT_LABEL (asm_out_file, l1);
if (for_eh)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__FRAME_BEGIN__");
else
......@@ -1413,6 +1345,26 @@ output_call_frame_info (for_eh)
fprintf (asm_out_file, "\t%s FDE address range", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
if (eh_ptr)
{
output_uleb128 (PTR_SIZE);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s FDE augmentation fields length",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
/* For now, a pointer to the translation unit's info will do.
??? Eventually this should point to the function's info. */
if (exception_table_p ())
ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__");
else
ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file, 0);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s pointer to exception region info",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
/* Loop through the Call Frame Instructions associated with
this FDE. */
......@@ -1420,16 +1372,9 @@ output_call_frame_info (for_eh)
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
output_cfi (cfi, fde);
/* Pad to a double word boundary. */
for (j = 0; j < fde_pad; ++j)
{
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
/* Pad the FDE out to an address sized boundary. */
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
ASM_OUTPUT_LABEL (asm_out_file, l2);
}
#ifndef EH_FRAME_SECTION
if (for_eh)
......@@ -1439,6 +1384,21 @@ output_call_frame_info (for_eh)
fputc ('\n', asm_out_file);
}
#endif
#ifdef MIPS_DEBUGGING_INFO
/* Work around Irix 6 assembler bug whereby labels at the end of a section
get a value of 0. Putting .align 0 after the label fixes it. */
ASM_OUTPUT_ALIGN (asm_out_file, 0);
#endif
}
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
int
dwarf2out_do_frame ()
{
return (write_symbols == DWARF2_DEBUG
|| (flag_exceptions && ! exceptions_via_longjmp));
}
/* Output a marker (i.e. a label) for the beginning of a function, before
......@@ -1508,9 +1468,9 @@ dwarf2out_frame_init ()
/* Generate the CFA instructions common to all FDE's. Do it now for the
sake of lookup_cfa. */
#ifdef INCOMING_RETURN_ADDR_RTX
/* On entry, the Canonical Frame Address is at SP+0. */
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, 0);
#ifdef DWARF2_UNWIND_INFO
/* On entry, the Canonical Frame Address is at SP. */
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
initial_return_save (INCOMING_RETURN_ADDR_RTX);
#endif
}
......@@ -1518,14 +1478,17 @@ dwarf2out_frame_init ()
void
dwarf2out_frame_finish ()
{
/* calculate sizes/offsets for FDEs. */
calc_fde_sizes ();
/* Output call frame information. */
#ifdef MIPS_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
output_call_frame_info (0);
if (flag_exceptions && ! exceptions_via_longjmp)
output_call_frame_info (1);
#else
if (write_symbols == DWARF2_DEBUG
|| (flag_exceptions && ! exceptions_via_longjmp))
output_call_frame_info (1);
#endif
}
#endif /* .debug_frame support */
......@@ -2191,33 +2154,6 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
#define SEPARATE_LINE_CODE_LABEL "LSM"
#endif
/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
newline is produced. When flag_verbose_asm is asserted, we add commnetary
at the end of the line, so we must avoid output of a newline here. */
#ifndef ASM_OUTPUT_DWARF_STRING
#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
do { \
register int slen = strlen(P); \
register char *p = (P); \
register int i; \
fprintf (FILE, "\t.ascii \""); \
for (i = 0; i < slen; i++) \
{ \
register int c = p[i]; \
if (c == '\"' || c == '\\') \
putc ('\\', FILE); \
if (c >= ' ' && c < 0177) \
putc (c, FILE); \
else \
{ \
fprintf (FILE, "\\%o", c); \
} \
} \
fprintf (FILE, "\\0\""); \
} \
while (0)
#endif
/* Convert a reference to the assembler name of a C-level name. This
macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
a string rather than writing to a file. */
......@@ -4922,9 +4858,13 @@ output_die (die)
break;
case dw_val_class_fde_ref:
ref_offset = fde_table[a->dw_attr_val.v.val_fde_index].dw_fde_offset;
fprintf (asm_out_file, "\t%s\t%s+0x%x", UNALIGNED_OFFSET_ASM_OP,
stripattributes (FRAME_SECTION), ref_offset);
{
char l1[20];
ASM_GENERATE_INTERNAL_LABEL
(l1, FDE_AFTER_SIZE_LABEL, a->dw_attr_val.v.val_fde_index * 2);
ASM_OUTPUT_DWARF_OFFSET (asm_out_file, l1);
fprintf (asm_out_file, " - %d", DWARF_OFFSET_SIZE);
}
break;
case dw_val_class_lbl_id:
......
......@@ -1262,7 +1262,8 @@ final (first, file, optimize, prescan)
new_block = 1;
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
dwarf2out_frame_debug (NULL_RTX);
if (write_symbols == DWARF2_DEBUG)
dwarf2out_frame_debug (NULL_RTX);
#endif
check_exception_handler_labels ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment