summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1997-09-10 18:00:28 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1997-09-10 18:00:28 +0000
commitd757b8c9a564c5dfe7a77df8a896cc8a8cb3009e (patch)
tree0928096722cf7e87c6973bd7bb029f787ab959db /gcc/dwarf2out.c
parentbb92b9f46e94086ea5307416fce72be178ab276d (diff)
downloadgcc-d757b8c9a564c5dfe7a77df8a896cc8a8cb3009e.tar.gz
dwarf2 EH support
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@15255 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c271
1 files changed, 205 insertions, 66 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index fac51352750..6789f01af84 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -20,19 +20,15 @@ You should have received a copy of the GNU General Public License
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
mechanism. The second part, controlled only by an #ifdef
DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
information. */
-#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
-
+#include "config.h"
+#include "defaults.h"
#include <stdio.h>
-#include <setjmp.h>
#include "dwarf2.h"
#include "tree.h"
#include "flags.h"
@@ -48,6 +44,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* #define NDEBUG 1 */
#include "assert.h"
+/* Decide whether we want to emit frame unwind information for the current
+ translation unit. */
+
+int
+dwarf2out_do_frame ()
+{
+ return (write_symbols == DWARF2_DEBUG
+#ifdef DWARF2_UNWIND_INFO
+ || (flag_exceptions && ! exceptions_via_longjmp)
+#endif
+ );
+}
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
#ifndef __GNUC__
#define inline
#endif
@@ -191,6 +202,7 @@ static unsigned reg_number PROTO((rtx));
Theses may be overridden in the tm.h file (if necessary) for a particular
assembler. */
+#ifdef OBJECT_FORMAT_ELF
#ifndef UNALIGNED_SHORT_ASM_OP
#define UNALIGNED_SHORT_ASM_OP ".2byte"
#endif
@@ -200,20 +212,12 @@ static unsigned reg_number PROTO((rtx));
#ifndef UNALIGNED_DOUBLE_INT_ASM_OP
#define UNALIGNED_DOUBLE_INT_ASM_OP ".8byte"
#endif
+#endif /* OBJECT_FORMAT_ELF */
+
#ifndef ASM_BYTE_OP
#define ASM_BYTE_OP ".byte"
#endif
-#ifndef UNALIGNED_OFFSET_ASM_OP
-#define UNALIGNED_OFFSET_ASM_OP \
- (DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
-#endif
-
-#ifndef UNALIGNED_WORD_ASM_OP
-#define UNALIGNED_WORD_ASM_OP \
- (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
-#endif
-
/* Data and reference forms for relocatable data. */
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
@@ -238,9 +242,6 @@ static unsigned reg_number PROTO((rtx));
#ifndef FRAME_SECTION
#define FRAME_SECTION ".debug_frame"
#endif
-#if !defined (EH_FRAME_SECTION) && defined (ASM_OUTPUT_SECTION_NAME)
-#define EH_FRAME_SECTION ".eh_frame"
-#endif
#ifndef FUNC_BEGIN_LABEL
#define FUNC_BEGIN_LABEL "LFB"
@@ -262,6 +263,23 @@ static unsigned reg_number PROTO((rtx));
fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION)
#endif
+#ifndef ASM_OUTPUT_DWARF_DATA1
+#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
+ fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
+#endif
+
+#ifdef UNALIGNED_INT_ASM_OP
+
+#ifndef UNALIGNED_OFFSET_ASM_OP
+#define UNALIGNED_OFFSET_ASM_OP \
+ (DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
+#endif
+
+#ifndef UNALIGNED_WORD_ASM_OP
+#define UNALIGNED_WORD_ASM_OP \
+ (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
+#endif
+
#ifndef ASM_OUTPUT_DWARF_DELTA2
#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
@@ -317,11 +335,6 @@ static unsigned reg_number PROTO((rtx));
} while (0)
#endif
-#ifndef ASM_OUTPUT_DWARF_DATA1
-#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
- fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
-#endif
-
#ifndef ASM_OUTPUT_DWARF_DATA2
#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) VALUE)
@@ -360,6 +373,43 @@ static unsigned reg_number PROTO((rtx));
} while (0)
#endif
+#else /* UNALIGNED_INT_ASM_OP */
+
+/* We don't have unaligned support, let's hope the normal output works for
+ .debug_frame. */
+
+#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, LABEL), PTR_SIZE, 1)
+
+#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
+ assemble_integer (gen_rtx (SYMBOL_REF, SImode, LABEL), 4, 1)
+
+#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
+ assemble_integer (gen_rtx (MINUS, HImode, \
+ gen_rtx (SYMBOL_REF, Pmode, LABEL1), \
+ gen_rtx (SYMBOL_REF, Pmode, LABEL2)), \
+ 2, 1)
+
+#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \
+ assemble_integer (gen_rtx (MINUS, SImode, \
+ gen_rtx (SYMBOL_REF, Pmode, LABEL1), \
+ gen_rtx (SYMBOL_REF, Pmode, LABEL2)), \
+ 4, 1)
+
+#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2) \
+ assemble_integer (gen_rtx (MINUS, Pmode, \
+ gen_rtx (SYMBOL_REF, Pmode, LABEL1), \
+ gen_rtx (SYMBOL_REF, Pmode, LABEL2)), \
+ PTR_SIZE, 1)
+
+#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
+ ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)
+
+#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
+ assemble_integer (GEN_INT (VALUE), 4, 1)
+
+#endif /* UNALIGNED_INT_ASM_OP */
+
/* 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. */
@@ -404,6 +454,14 @@ static unsigned reg_number PROTO((rtx));
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif
+/* Hook used by __throw. */
+
+rtx
+expand_builtin_dwarf_fp_regnum ()
+{
+ return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM));
+}
+
/* The offset from the incoming value of %sp to the top of the stack frame
for the current function. */
#ifndef INCOMING_FRAME_SP_OFFSET
@@ -497,6 +555,8 @@ dwarf_cfi_name (cfi_opc)
/* GNU extensions */
case DW_CFA_GNU_window_save:
return "DW_CFA_GNU_window_save";
+ case DW_CFA_GNU_args_size:
+ return "DW_CFA_GNU_args_size";
default:
return "DW_CFA_<unknown>";
@@ -638,6 +698,9 @@ static long cfa_offset;
static unsigned cfa_store_reg;
static long cfa_store_offset;
+/* The running total of the size of arguments pushed onto the stack. */
+static long args_size;
+
/* Entry point to update the canonical frame address (CFA).
LABEL is passed to add_fde_cfi. The value of CFA is now to be
calculated from REG+OFFSET. */
@@ -743,6 +806,20 @@ dwarf2out_window_save (label)
add_fde_cfi (label, cfi);
}
+/* Add a CFI to update the running total of the size of arguments
+ pushed onto the stack. */
+
+void
+dwarf2out_args_size (label, size)
+ char *label;
+ long size;
+{
+ register dw_cfi_ref cfi = new_cfi ();
+ cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
+ cfi->dw_cfi_oprnd1.dw_cfi_offset = size;
+ 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. */
@@ -828,6 +905,67 @@ initial_return_save (rtl)
reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset);
}
+/* Check INSN to see if it looks like a push or a stack adjustment, and
+ make a note of it if it does. EH uses this information to find out how
+ much extra space it needs to pop off the stack. */
+
+static void
+dwarf2out_stack_adjust (insn)
+ rtx insn;
+{
+ rtx src, dest;
+ enum rtx_code code;
+ long offset;
+ char *label;
+
+ if (GET_CODE (insn) != SET)
+ return;
+
+ src = SET_SRC (insn);
+ dest = SET_DEST (insn);
+ if (dest == stack_pointer_rtx)
+ {
+ /* (set (reg sp) (plus (reg sp) (const_int))) */
+ code = GET_CODE (src);
+ if (! (code == PLUS || code == MINUS)
+ || XEXP (src, 0) != stack_pointer_rtx
+ || GET_CODE (XEXP (src, 1)) != CONST_INT)
+ return;
+
+ offset = INTVAL (XEXP (src, 1));
+ }
+ else if (GET_CODE (dest) == MEM)
+ {
+ /* (set (mem (pre_dec (reg sp))) (foo)) */
+ src = XEXP (dest, 0);
+ code = GET_CODE (src);
+
+ if (! (code == PRE_DEC || code == PRE_INC)
+ || XEXP (src, 0) != stack_pointer_rtx)
+ return;
+
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ }
+ else
+ return;
+
+ if (code == PLUS || code == PRE_INC)
+ offset = -offset;
+ if (cfa_reg == STACK_POINTER_REGNUM)
+ cfa_offset += offset;
+
+#ifndef STACK_GROWS_DOWNWARD
+ offset = -offset;
+#endif
+ args_size += offset;
+ if (args_size < 0)
+ args_size = 0;
+
+ label = dwarf2out_cfi_label ();
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ dwarf2out_args_size (label, args_size);
+}
+
/* 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. */
@@ -857,6 +995,12 @@ dwarf2out_frame_debug (insn)
return;
}
+ if (! RTX_FRAME_RELATED_P (insn))
+ {
+ dwarf2out_stack_adjust (PATTERN (insn));
+ return;
+ }
+
label = dwarf2out_cfi_label ();
insn = PATTERN (insn);
@@ -903,13 +1047,21 @@ dwarf2out_frame_debug (insn)
abort ();
}
+ if (XEXP (src, 0) == hard_frame_pointer_rtx)
+ {
+ /* Restoring SP from FP in the epilogue. */
+ assert (cfa_reg == HARD_FRAME_POINTER_REGNUM);
+ cfa_reg = STACK_POINTER_REGNUM;
+ }
+ else
+ assert (XEXP (src, 0) == stack_pointer_rtx);
+
if (GET_CODE (src) == PLUS)
offset = -offset;
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset += offset;
if (cfa_store_reg == STACK_POINTER_REGNUM)
cfa_store_offset += offset;
- assert (XEXP (src, 0) == stack_pointer_rtx);
}
else
{
@@ -953,7 +1105,7 @@ dwarf2out_frame_debug (insn)
case PRE_INC:
case PRE_DEC:
offset = GET_MODE_SIZE (GET_MODE (dest));
- if (GET_CODE (src) == PRE_INC)
+ if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
offset = -offset;
assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
@@ -1196,12 +1348,29 @@ output_cfi (cfi, fde)
break;
case DW_CFA_GNU_window_save:
break;
+ case DW_CFA_GNU_args_size:
+ output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ fputc ('\n', asm_out_file);
+ break;
default:
break;
}
}
}
+#if !defined (EH_FRAME_SECTION)
+#if defined (EH_FRAME_SECTION_ASM_OP)
+#define EH_FRAME_SECTION() eh_frame_section();
+#else
+#if defined (ASM_OUTPUT_SECTION_NAME)
+#define EH_FRAME_SECTION() \
+ do { \
+ named_section (NULL_TREE, ".eh_frame", 0); \
+ } while (0)
+#endif
+#endif
+#endif
+
/* Output the call frame information used to used to record information
that relates to calculating the frame pointer, and records the
location of saved registers. */
@@ -1231,9 +1400,13 @@ output_call_frame_info (for_eh)
if (for_eh)
{
#ifdef EH_FRAME_SECTION
- ASM_OUTPUT_SECTION_NAME (asm_out_file, NULL_TREE, EH_FRAME_SECTION, 0);
+ EH_FRAME_SECTION ();
#else
+ tree label = (tree) get_file_function_name ('F');
+
data_section ();
+ ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
+ ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
#endif
assemble_label ("__FRAME_BEGIN__");
}
@@ -1272,9 +1445,9 @@ output_call_frame_info (for_eh)
fputc ('\n', asm_out_file);
if (eh_ptr)
{
- /* The "z" augmentation was defined by SGI; the FDE contains a pointer
+ /* The FDE contains a pointer
to the exception region info for the frame. */
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "z");
+ ASM_OUTPUT_DWARF_STRING (asm_out_file, "e");
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START);
}
@@ -1302,14 +1475,6 @@ 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);
@@ -1355,19 +1520,9 @@ output_call_frame_info (for_eh)
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);
-
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__");
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s pointer to exception region info",
ASM_COMMENT_START);
@@ -1399,16 +1554,6 @@ output_call_frame_info (for_eh)
#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
the prologue. */
@@ -1443,6 +1588,8 @@ dwarf2out_begin_prologue ()
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
fde->dw_fde_cfi = NULL;
+
+ args_size = 0;
}
/* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -9142,10 +9289,6 @@ dwarf2out_init (asm_out_file, main_input_filename)
gen_compile_unit_die (main_input_filename);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
-
- /* Initialize the frame unwind information. Eventually this should be
- called from compile_file instead. */
- dwarf2out_frame_init ();
}
/* Output stuff that dwarf requires at the end of every file,
@@ -9202,10 +9345,6 @@ dwarf2out_finish ()
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0);
#endif
- /* Output the frame unwind information. Eventually this should be called
- from compile_file instead. */
- dwarf2out_frame_finish ();
-
/* Output the source line correspondence table. */
if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
{