aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/i386/i386.h3
-rw-r--r--gcc/defaults.h6
-rw-r--r--gcc/dwarf2out.c336
-rw-r--r--gcc/final.c3
4 files changed, 149 insertions, 199 deletions
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 9cc51d9..8056af7 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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. */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 1bf5d6a..6511338 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -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
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index aed0de4..b20683d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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:
diff --git a/gcc/final.c b/gcc/final.c
index 91ad498..d36e3d6 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -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 ();