/* Output Dwarf2 format symbol table information from the GNU C compiler.
- Copyright (C) 1992, 93, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 95-98, 1999 Free Software Foundation, Inc.
Contributed by Gary Funck (gary@intrepid.com).
Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
Extensively modified by Jason Merrill (jason@cygnus.com).
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. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* The first part of this file deals with the DWARF 2 frame unwind
information, which is also used by the GCC efficient exception handling
#include "dwarf2.h"
#include "dwarf2out.h"
#include "toplev.h"
+#include "dyn-string.h"
/* We cannot use <assert.h> in GCC source, since that would include
GCC's assert.h, which may not be compatible with the host compiler. */
dwarf2out_do_frame ()
{
return (write_symbols == DWARF2_DEBUG
+#ifdef DWARF2_FRAME_INFO
+ || DWARF2_FRAME_INFO
+#endif
#ifdef DWARF2_UNWIND_INFO
|| (flag_exceptions && ! exceptions_via_longjmp)
#endif
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
-#ifndef __GNUC__
-#define inline
-#endif
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
/* Forward declarations for functions defined in this file. */
-static char *stripattributes PROTO((char *));
-static char *dwarf_cfi_name PROTO((unsigned));
+static char *stripattributes PROTO((const char *));
+static const char *dwarf_cfi_name PROTO((unsigned));
static dw_cfi_ref new_cfi PROTO((void));
static void add_cfi PROTO((dw_cfi_ref *, dw_cfi_ref));
static unsigned long size_of_uleb128 PROTO((unsigned long));
static void output_call_frame_info PROTO((int));
static unsigned reg_number PROTO((rtx));
static void dwarf2out_stack_adjust PROTO((rtx));
+static void dwarf2out_frame_debug_expr PROTO((rtx, char *));
/* Definitions of defaults for assembler-dependent names of various
pseudo-ops and section names.
#ifndef ASM_OUTPUT_DWARF_DATA1
#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
- fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
+ fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) (VALUE))
#endif
#ifndef ASM_OUTPUT_DWARF_DELTA1
} while (0)
#endif
+/* ??? This macro takes an RTX in dwarfout.c and a string in dwarf2out.c.
+ We resolve the conflict by creating a new macro ASM_OUTPUT_DWARF2_ADDR_CONST
+ for ports that want to support both DWARF1 and DWARF2. This needs a better
+ solution. See also the comments in sparc/sp64-elf.h. */
+#ifdef ASM_OUTPUT_DWARF2_ADDR_CONST
+#undef ASM_OUTPUT_DWARF_ADDR_CONST
+#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
+ ASM_OUTPUT_DWARF2_ADDR_CONST (FILE, ADDR)
+#endif
+
#ifndef ASM_OUTPUT_DWARF_ADDR_CONST
#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR))
#ifndef ASM_OUTPUT_DWARF_DATA2
#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
- fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) VALUE)
+ fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) (VALUE))
#endif
#ifndef ASM_OUTPUT_DWARF_DATA4
#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
- fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) VALUE)
+ fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) (VALUE))
#endif
#ifndef ASM_OUTPUT_DWARF_DATA
#define ASM_OUTPUT_DWARF_DATA(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP, \
- (unsigned long) VALUE)
+ (unsigned long) (VALUE))
#endif
#ifndef ASM_OUTPUT_DWARF_ADDR_DATA
#define ASM_OUTPUT_DWARF_ADDR_DATA(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_WORD_ASM_OP, \
- (unsigned long) VALUE)
+ (unsigned long) (VALUE))
#endif
#ifndef ASM_OUTPUT_DWARF_DATA8
do { \
if (WORDS_BIG_ENDIAN) \
{ \
- fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
- fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
+ fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, (HIGH_VALUE));\
+ fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (LOW_VALUE));\
} \
else \
{ \
- fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
- fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
+ fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, (LOW_VALUE)); \
+ fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (HIGH_VALUE)); \
} \
} while (0)
#endif
#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)), \
+ 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)), \
+ 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)), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
PTR_SIZE, 1)
#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
do { \
register int slen = strlen(P); \
- register char *p = (P); \
+ register const 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) \
+ if (ISPRINT(c)) \
putc (c, FILE); \
else \
{ \
#endif
/* Return a pointer to a copy of the section string name S with all
- attributes stripped off. */
+ attributes stripped off, and an asterisk prepended (for assemble_name). */
static inline char *
stripattributes (s)
- char *s;
+ const char *s;
{
- char *stripped = xstrdup (s);
+ char *stripped = xmalloc (strlen (s) + 2);
char *p = stripped;
- while (*p && *p != ',')
- p++;
+ *p++ = '*';
+
+ while (*s && *s != ',')
+ *p++ = *s++;
*p = '\0';
return stripped;
}
else
{
+ /* Initialize last_end to be larger than any possible
+ DWARF_FRAME_REGNUM. */
+ int last_end = 0x7fffffff;
--n_ranges;
t = build_int_2 (ranges[n_ranges].size, 0);
- size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
- for (; n_ranges--; )
+ do
{
- if ((DWARF_FRAME_REGNUM (ranges[n_ranges].end)
- - DWARF_FRAME_REGNUM (ranges[n_ranges].beg))
- != ranges[n_ranges].end - ranges[n_ranges].beg)
+ int beg = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
+ int end = DWARF_FRAME_REGNUM (ranges[n_ranges].end);
+ if (beg < 0)
+ continue;
+ if (end >= last_end)
abort ();
- if (DWARF_FRAME_REGNUM (ranges[n_ranges].beg) >= size)
+ last_end = end;
+ if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg)
abort ();
- size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
- build_int_2 (DWARF_FRAME_REGNUM
- (ranges[n_ranges].end), 0)));
+ build_int_2 (end, 0)));
t = fold (build (COND_EXPR, integer_type_node, t2,
build_int_2 (ranges[n_ranges].size, 0), t));
}
+ while (--n_ranges >= 0);
}
return expand_expr (t, target, Pmode, 0);
}
/* Convert a DWARF call frame info. operation to its string name */
-static char *
+static const char *
dwarf_cfi_name (cfi_opc)
register unsigned cfi_opc;
{
initial_return_save (rtl)
register rtx rtl;
{
- unsigned reg = -1;
+ unsigned int reg = (unsigned int) -1;
long offset = 0;
switch (GET_CODE (rtl))
dwarf2out_args_size (label, args_size);
}
-/* Record call frame debugging information for INSN, which either
+/* A temporary register used in adjusting SP or setting up the store_reg. */
+static unsigned cfa_temp_reg;
+
+/* A temporary value used in adjusting SP or setting up the store_reg. */
+static long cfa_temp_value;
+
+/* Record call frame debugging information for an expression, 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. */
+ register to the stack. */
-void
-dwarf2out_frame_debug (insn)
- rtx insn;
+static void
+dwarf2out_frame_debug_expr (expr, label)
+ rtx expr;
+ char *label;
{
- char *label;
rtx src, dest;
long offset;
+
+ /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
+ the PARALLEL independantly. The first element is always processed if
+ it is a SET. This is for backward compatability. Other elements
+ are processed only if they are SETs and the RTX_FRAME_RELATED_P
+ flag is set in them. */
- /* A temporary register used in adjusting SP or setting up the store_reg. */
- static unsigned cfa_temp_reg;
- static long cfa_temp_value;
-
- if (insn == NULL_RTX)
- {
- /* Set up state for generating call frame debug info. */
- lookup_cfa (&cfa_reg, &cfa_offset);
- if (cfa_reg != DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
- abort ();
- cfa_reg = STACK_POINTER_REGNUM;
- cfa_store_reg = cfa_reg;
- cfa_store_offset = cfa_offset;
- cfa_temp_reg = -1;
- cfa_temp_value = 0;
- return;
- }
-
- if (! RTX_FRAME_RELATED_P (insn))
- {
- dwarf2out_stack_adjust (insn);
+ if (GET_CODE (expr) == PARALLEL)
+ {
+ int par_index;
+ int limit = XVECLEN (expr, 0);
+
+ for (par_index = 0; par_index < limit; par_index++)
+ {
+ rtx x = XVECEXP (expr, 0, par_index);
+
+ if (GET_CODE (x) == SET &&
+ (RTX_FRAME_RELATED_P (x) || par_index == 0))
+ dwarf2out_frame_debug_expr (x, label);
+ }
return;
}
-
- label = dwarf2out_cfi_label ();
-
- insn = PATTERN (insn);
- /* Assume that in a PARALLEL prologue insn, only the first elt is
- significant. Currently this is true. */
- if (GET_CODE (insn) == PARALLEL)
- insn = XVECEXP (insn, 0, 0);
- if (GET_CODE (insn) != SET)
+
+ if (GET_CODE (expr) != SET)
abort ();
- src = SET_SRC (insn);
- dest = SET_DEST (insn);
+ src = SET_SRC (expr);
+ dest = SET_DEST (expr);
switch (GET_CODE (dest))
{
case REG:
/* Update the CFA rule wrt SP or FP. Make sure src is
- relative to the current CFA register. */
+ relative to the current CFA register. */
switch (GET_CODE (src))
- {
- /* Setting FP from SP. */
- case REG:
- if (cfa_reg != REGNO (src))
- abort ();
- if (REGNO (dest) != STACK_POINTER_REGNUM
+ {
+ /* Setting FP from SP. */
+ case REG:
+ if (cfa_reg != (unsigned) REGNO (src))
+ abort ();
+ if (REGNO (dest) != STACK_POINTER_REGNUM
&& !(frame_pointer_needed
&& REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
- abort ();
- cfa_reg = REGNO (dest);
- break;
+ abort ();
+ cfa_reg = REGNO (dest);
+ break;
- case PLUS:
- case MINUS:
- if (dest == stack_pointer_rtx)
- {
+ case PLUS:
+ case MINUS:
+ if (dest == stack_pointer_rtx)
+ {
/* Adjusting SP. */
switch (GET_CODE (XEXP (src, 1)))
{
offset = INTVAL (XEXP (src, 1));
break;
case REG:
- if (REGNO (XEXP (src, 1)) != cfa_temp_reg)
+ if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
abort ();
offset = cfa_temp_value;
break;
if (XEXP (src, 0) == hard_frame_pointer_rtx)
{
/* Restoring SP from FP in the epilogue. */
- if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
abort ();
cfa_reg = STACK_POINTER_REGNUM;
}
cfa_offset += offset;
if (cfa_store_reg == STACK_POINTER_REGNUM)
cfa_store_offset += offset;
- }
+ }
else if (dest == hard_frame_pointer_rtx)
{
- /* Either setting the FP from an offset of the SP,
- or adjusting the FP */
+ /* Either setting the FP from an offset of the SP,
+ or adjusting the FP */
if (! frame_pointer_needed
|| REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
abort ();
- if (XEXP (src, 0) == stack_pointer_rtx
- && GET_CODE (XEXP (src, 1)) == CONST_INT)
- {
+ if (XEXP (src, 0) == stack_pointer_rtx
+ && GET_CODE (XEXP (src, 1)) == CONST_INT)
+ {
if (cfa_reg != STACK_POINTER_REGNUM)
abort ();
- offset = INTVAL (XEXP (src, 1));
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- cfa_offset += offset;
- cfa_reg = HARD_FRAME_POINTER_REGNUM;
- }
- else if (XEXP (src, 0) == hard_frame_pointer_rtx
- && GET_CODE (XEXP (src, 1)) == CONST_INT)
- {
- if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
+ offset = INTVAL (XEXP (src, 1));
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ cfa_offset += offset;
+ cfa_reg = HARD_FRAME_POINTER_REGNUM;
+ }
+ else if (XEXP (src, 0) == hard_frame_pointer_rtx
+ && GET_CODE (XEXP (src, 1)) == CONST_INT)
+ {
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
abort ();
- offset = INTVAL (XEXP (src, 1));
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- cfa_offset += offset;
- }
-
- else
- abort();
+ offset = INTVAL (XEXP (src, 1));
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ cfa_offset += offset;
+ }
+
+ else
+ abort();
}
- else
- {
+ else
+ {
if (GET_CODE (src) != PLUS
|| XEXP (src, 1) != stack_pointer_rtx)
abort ();
if (GET_CODE (XEXP (src, 0)) != REG
- || REGNO (XEXP (src, 0)) != cfa_temp_reg)
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
abort ();
if (cfa_reg != STACK_POINTER_REGNUM)
abort ();
cfa_store_reg = REGNO (dest);
cfa_store_offset = cfa_offset - cfa_temp_value;
- }
- break;
+ }
+ break;
- case CONST_INT:
- cfa_temp_reg = REGNO (dest);
- cfa_temp_value = INTVAL (src);
- break;
+ case CONST_INT:
+ cfa_temp_reg = REGNO (dest);
+ cfa_temp_value = INTVAL (src);
+ break;
- case IOR:
- if (GET_CODE (XEXP (src, 0)) != REG
- || REGNO (XEXP (src, 0)) != cfa_temp_reg
- || REGNO (dest) != cfa_temp_reg
+ case IOR:
+ if (GET_CODE (XEXP (src, 0)) != REG
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
+ || (unsigned) REGNO (dest) != cfa_temp_reg
|| GET_CODE (XEXP (src, 1)) != CONST_INT)
- abort ();
- cfa_temp_value |= INTVAL (XEXP (src, 1));
- break;
+ abort ();
+ cfa_temp_value |= INTVAL (XEXP (src, 1));
+ break;
- default:
- abort ();
- }
+ 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. */
+ CFA register. */
if (GET_CODE (src) != REG)
abort ();
switch (GET_CODE (XEXP (dest, 0)))
case PLUS:
case MINUS:
offset = INTVAL (XEXP (XEXP (dest, 0), 1));
- if (GET_CODE (src) == MINUS)
+ if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset;
- if (cfa_store_reg != REGNO (XEXP (XEXP (dest, 0), 0)))
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
abort ();
offset -= cfa_store_offset;
break;
+ /* Without an offset. */
+ case REG:
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0)))
+ abort();
+ offset = -cfa_store_offset;
+ break;
+
default:
abort ();
}
}
}
+
+/* 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_frame_debug (insn)
+ rtx insn;
+{
+ char *label;
+ rtx src;
+
+ if (insn == NULL_RTX)
+ {
+ /* Set up state for generating call frame debug info. */
+ lookup_cfa (&cfa_reg, &cfa_offset);
+ if (cfa_reg != DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
+ abort ();
+ cfa_reg = STACK_POINTER_REGNUM;
+ cfa_store_reg = cfa_reg;
+ cfa_store_offset = cfa_offset;
+ cfa_temp_reg = -1;
+ cfa_temp_value = 0;
+ return;
+ }
+
+ if (! RTX_FRAME_RELATED_P (insn))
+ {
+ dwarf2out_stack_adjust (insn);
+ return;
+ }
+
+ label = dwarf2out_cfi_label ();
+
+ src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+ if (src)
+ insn = XEXP (src, 0);
+ else
+ insn = PATTERN (insn);
+
+ dwarf2out_frame_debug_expr (insn, label);
+}
+
/* Return the size of an unsigned LEB128 quantity. */
static inline unsigned long
}
}
-#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. */
#else
tree label = get_file_function_name ('F');
- data_section ();
+ force_data_section ();
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
fputc ('\n', asm_out_file);
ASM_OUTPUT_LABEL (asm_out_file, l1);
+ /* ??? This always emits a 4 byte offset when for_eh is true, but it
+ emits a target dependent sized offset when for_eh is not true.
+ This inconsistency may confuse gdb. The only case where we need a
+ non-4 byte offset is for the Irix6 N64 ABI, so we may lose SGI
+ compatibility if we emit a 4 byte offset. We need a 4 byte offset
+ though in order to be compatible with the dwarf_fde struct in frame.c.
+ If the for_eh case is changed, then the struct in frame.c has
+ to be adjusted appropriately. */
if (for_eh)
- ASM_OUTPUT_DWARF_DELTA (asm_out_file, l1, "__FRAME_BEGIN__");
+ ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l1, "__FRAME_BEGIN__");
else
ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION));
if (flag_debug_asm)
dwarf2out_frame_init ()
{
/* Allocate the initial hunk of the fde_table. */
- fde_table
- = (dw_fde_ref) xmalloc (FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
- bzero ((char *) fde_table, FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
+ fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node));
fde_table_allocated = FDE_TABLE_INCREMENT;
fde_table_in_use = 0;
/* And now, the support for symbolic debugging information. */
#ifdef DWARF2_DEBUGGING_INFO
-extern char *getpwd ();
-
/* NOTE: In the comments in this file, many references are made to
"Debugging Information Entries". This term is abbreviated as `DIE'
throughout the remainder of this file. */
dw_val_class_die_ref,
dw_val_class_fde_ref,
dw_val_class_lbl_id,
- dw_val_class_section_offset,
+ dw_val_class_lbl_offset,
dw_val_class_str
}
dw_val_class;
unsigned val_fde_index;
char *val_str;
char *val_lbl_id;
- char *val_section;
unsigned char val_flag;
}
v;
extern int flag_traditional;
extern char *version_string;
-extern char *language_string;
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
#define DWARF_ARANGES_HEADER_SIZE \
(DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
+/* The default is to have gcc emit the line number tables. */
+#ifndef DWARF2_ASM_LINE_DEBUG_INFO
+#define DWARF2_ASM_LINE_DEBUG_INFO 0
+#endif
+
/* Define the architecture-dependent minimum instruction length (in bytes).
In this implementation of DWARF, this field is used for information
purposes only. Since GCC generates assembly language, we have
be enough for most typical programs. */
#define PENDING_TYPES_INCREMENT 64
+/* A pointer to the base of a list of incomplete types which might be
+ completed at some later time. */
+
+static tree *incomplete_types_list;
+
+/* Number of elements currently allocated for the incomplete_types_list. */
+static unsigned incomplete_types_allocated;
+
+/* Number of elements of incomplete_types_list currently in use. */
+static unsigned incomplete_types;
+
+/* Size (in elements) of increments by which we may expand the incomplete
+ types list. Actually, a single hunk of space of this size should
+ be enough for most typical programs. */
+#define INCOMPLETE_TYPES_INCREMENT 64
+
/* Record whether the function being analyzed contains inlined functions. */
static int current_function_has_inlines;
#if 0 && defined (MIPS_DEBUGGING_INFO)
/* Forward declarations for functions defined in this file. */
-static void addr_const_to_string PROTO((char *, rtx));
+static void addr_const_to_string PROTO((dyn_string_t, rtx));
static char *addr_to_string PROTO((rtx));
static int is_pseudo_reg PROTO((rtx));
static tree type_main_variant PROTO((tree));
static int is_tagged_type PROTO((tree));
-static char *dwarf_tag_name PROTO((unsigned));
-static char *dwarf_attr_name PROTO((unsigned));
-static char *dwarf_form_name PROTO((unsigned));
-static char *dwarf_stack_op_name PROTO((unsigned));
+static const char *dwarf_tag_name PROTO((unsigned));
+static const char *dwarf_attr_name PROTO((unsigned));
+static const char *dwarf_form_name PROTO((unsigned));
+static const char *dwarf_stack_op_name PROTO((unsigned));
#if 0
-static char *dwarf_type_encoding_name PROTO((unsigned));
+static const char *dwarf_type_encoding_name PROTO((unsigned));
#endif
static tree decl_ultimate_origin PROTO((tree));
static tree block_ultimate_origin PROTO((tree));
enum dwarf_attribute,
unsigned, long *));
static void add_AT_string PROTO((dw_die_ref,
- enum dwarf_attribute, char *));
+ enum dwarf_attribute,
+ const char *));
static void add_AT_die_ref PROTO((dw_die_ref,
enum dwarf_attribute,
dw_die_ref));
enum dwarf_attribute, char *));
static void add_AT_lbl_id PROTO((dw_die_ref,
enum dwarf_attribute, char *));
-static void add_AT_section_offset PROTO((dw_die_ref,
+static void add_AT_lbl_offset PROTO((dw_die_ref,
enum dwarf_attribute, char *));
static int is_extern_subr_die PROTO((dw_die_ref));
static dw_attr_ref get_AT PROTO((dw_die_ref,
static unsigned long sibling_offset PROTO((dw_die_ref));
static void output_die PROTO((dw_die_ref));
static void output_compilation_unit_header PROTO((void));
-static char *dwarf2_name PROTO((tree, int));
+static const char *dwarf2_name PROTO((tree, int));
static void add_pubname PROTO((tree, dw_die_ref));
static void output_pubnames PROTO((void));
static void add_arange PROTO((tree, dw_die_ref));
static dw_loc_descr_ref reg_loc_descriptor PROTO((rtx));
static dw_loc_descr_ref based_loc_descr PROTO((unsigned, long));
static int is_based_loc PROTO((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx));
+static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx, enum machine_mode mode));
static dw_loc_descr_ref concat_loc_descriptor PROTO((rtx, rtx));
static dw_loc_descr_ref loc_descriptor PROTO((rtx));
static unsigned ceiling PROTO((unsigned, unsigned));
static void add_data_member_location_attribute PROTO((dw_die_ref, tree));
static void add_const_value_attribute PROTO((dw_die_ref, rtx));
static void add_location_or_const_value_attribute PROTO((dw_die_ref, tree));
-static void add_name_attribute PROTO((dw_die_ref, char *));
+static void add_name_attribute PROTO((dw_die_ref, const char *));
static void add_bound_info PROTO((dw_die_ref,
enum dwarf_attribute, tree));
static void add_subscript_info PROTO((dw_die_ref, tree));
static void decls_for_scope PROTO((tree, dw_die_ref, int));
static int is_redundant_typedef PROTO((tree));
static void gen_decl_die PROTO((tree, dw_die_ref));
-static unsigned lookup_filename PROTO((char *));
+static unsigned lookup_filename PROTO((const char *));
+static void add_incomplete_type PROTO((tree));
+static void retry_incomplete_types PROTO((void));
/* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION
#define BSS_SECTION ".bss"
#endif
+/* Labels we insert at beginning sections we can reference instead of
+ the section names themselves. */
+
+#ifndef TEXT_SECTION_LABEL
+#define TEXT_SECTION_LABEL "Ltext"
+#endif
+#ifndef DEBUG_LINE_SECTION_LABEL
+#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
+#endif
+#ifndef DEBUG_INFO_SECTION_LABEL
+#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
+#endif
+#ifndef ABBREV_SECTION_LABEL
+#define ABBREV_SECTION_LABEL "Ldebug_abbrev"
+#endif
+
/* Definitions of defaults for formats and names of various special
(artificial) labels which may be generated within this file (when the -g
typically, overriding these defaults is unnecessary. */
static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
#ifndef TEXT_END_LABEL
#define TEXT_END_LABEL "Letext"
macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
a string rather than writing to a file. */
#ifndef ASM_NAME_TO_STRING
-#define ASM_NAME_TO_STRING(STR, NAME) \
- do { \
- if ((NAME)[0] == '*') \
- strcpy (STR, NAME+1); \
- else \
- strcpy (STR, NAME); \
- } \
+#define ASM_NAME_TO_STRING(STR, NAME) \
+ do { \
+ if ((NAME)[0] == '*') \
+ dyn_string_append (STR, NAME + 1); \
+ else \
+ { \
+ const char *newstr; \
+ STRIP_NAME_ENCODING (newstr, NAME); \
+ dyn_string_append (STR, user_label_prefix); \
+ dyn_string_append (STR, newstr); \
+ } \
+ } \
while (0)
#endif
\f
static void
addr_const_to_string (str, x)
- char *str;
+ dyn_string_t str;
rtx x;
{
char buf1[256];
- char buf2[256];
restart:
- str[0] = '\0';
switch (GET_CODE (x))
{
case PC:
if (flag_pic)
- strcat (str, ",");
+ dyn_string_append (str, ",");
else
abort ();
break;
case SYMBOL_REF:
- ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
- strcat (str, buf1);
+ ASM_NAME_TO_STRING (str, XSTR (x, 0));
break;
case LABEL_REF:
ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
- ASM_NAME_TO_STRING (buf2, buf1);
- strcat (str, buf2);
+ ASM_NAME_TO_STRING (str, buf1);
break;
case CODE_LABEL:
ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
- ASM_NAME_TO_STRING (buf2, buf1);
- strcat (str, buf2);
+ ASM_NAME_TO_STRING (str, buf1);
break;
case CONST_INT:
sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- strcat (str, buf1);
+ dyn_string_append (str, buf1);
break;
case CONST:
/* This used to output parentheses around the expression, but that does
not work on the 386 (either ATT or BSD assembler). */
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
break;
case CONST_DOUBLE:
else
sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
CONST_DOUBLE_LOW (x));
- strcat (str, buf1);
+ dyn_string_append (str, buf1);
}
else
/* We can't handle floating point constants; PRINT_OPERAND must
/* Some assemblers need integer constants to appear last (eg masm). */
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
{
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 1));
if (INTVAL (XEXP (x, 0)) >= 0)
- strcat (str, "+");
+ dyn_string_append (str, "+");
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
}
else
{
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
if (INTVAL (XEXP (x, 1)) >= 0)
- strcat (str, "+");
+ dyn_string_append (str, "+");
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 1));
}
break;
if (GET_CODE (x) != MINUS)
goto restart;
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- strcat (str, "-");
+ addr_const_to_string (str, XEXP (x, 0));
+ dyn_string_append (str, "-");
if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& INTVAL (XEXP (x, 1)) < 0)
{
- strcat (str, ASM_OPEN_PAREN);
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- strcat (str, ASM_CLOSE_PAREN);
+ dyn_string_append (str, ASM_OPEN_PAREN);
+ addr_const_to_string (str, XEXP (x, 1));
+ dyn_string_append (str, ASM_CLOSE_PAREN);
}
else
- {
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- }
+ addr_const_to_string (str, XEXP (x, 1));
break;
case ZERO_EXTEND:
case SIGN_EXTEND:
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
break;
default:
addr_to_string (x)
rtx x;
{
- char buf[1024];
- addr_const_to_string (buf, x);
- return xstrdup (buf);
+ dyn_string_t ds = dyn_string_new (256);
+ char *s;
+
+ addr_const_to_string (ds, x);
+
+ /* Return the dynamically allocated string, but free the
+ dyn_string_t itself. */
+ s = ds->s;
+ free (ds);
+ return s;
}
/* Test if rtl node points to a pseudo register. */
/* Convert a DIE tag into its string name. */
-static char *
+static const char *
dwarf_tag_name (tag)
register unsigned tag;
{
/* Convert a DWARF attribute code into its string name. */
-static char *
+static const char *
dwarf_attr_name (attr)
register unsigned attr;
{
/* Convert a DWARF value form code into its string name. */
-static char *
+static const char *
dwarf_form_name (form)
register unsigned form;
{
/* Convert a DWARF stack opcode into its string name. */
-static char *
+static const char *
dwarf_stack_op_name (op)
register unsigned op;
{
/* Convert a DWARF type code into its string name. */
#if 0
-static char *
+static const char *
dwarf_type_encoding_name (enc)
register unsigned enc;
{
decl_ultimate_origin (decl)
register tree decl;
{
- register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
-
- if (immediate_origin == NULL_TREE)
- return NULL_TREE;
- else
- {
- register tree ret_val;
- register tree lookahead = immediate_origin;
-
- do
- {
- ret_val = lookahead;
- lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
- }
- while (lookahead != NULL && lookahead != ret_val);
+#ifdef ENABLE_CHECKING
+ if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
+ /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+ most distant ancestor, this should never happen. */
+ abort ();
+#endif
- return ret_val;
- }
+ return DECL_ABSTRACT_ORIGIN (decl);
}
/* Determine the "ultimate origin" of a block. The block may be an inlined
add_AT_string (die, attr_kind, str)
register dw_die_ref die;
register enum dwarf_attribute attr_kind;
- register char *str;
+ register const char *str;
{
register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
/* Add a section offset attribute value to a DIE. */
static inline void
-add_AT_section_offset (die, attr_kind, section)
+add_AT_lbl_offset (die, attr_kind, label)
register dw_die_ref die;
register enum dwarf_attribute attr_kind;
- register char *section;
+ register char *label;
{
register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_section_offset;
- attr->dw_attr_val.v.val_section = section;
+ attr->dw_attr_val.val_class = dw_val_class_lbl_offset;
+ attr->dw_attr_val.v.val_lbl_id = label;
add_dwarf_attr (die, attr);
}
register enum dwarf_attribute attr_kind;
{
register dw_attr_ref a;
- register dw_attr_ref removed = NULL;;
+ register dw_attr_ref removed = NULL;
if (die != NULL)
{
fprintf (outfile, "die -> <null>");
break;
case dw_val_class_lbl_id:
+ case dw_val_class_lbl_offset:
fprintf (outfile, "label: %s", a->dw_attr_val.v.val_lbl_id);
break;
- case dw_val_class_section_offset:
- fprintf (outfile, "section: %s", a->dw_attr_val.v.val_section);
- break;
case dw_val_class_str:
if (a->dw_attr_val.v.val_str != NULL)
fprintf (outfile, "\"%s\"", a->dw_attr_val.v.val_str);
{
print_indent = 0;
print_die (comp_unit_die, stderr);
- print_dwarf_line_table (stderr);
+ if (! DWARF2_ASM_LINE_DEBUG_INFO)
+ print_dwarf_line_table (stderr);
}
\f
/* Traverse the DIE, and add a sibling attribute if it may have the
build_abbrev_table (c);
}
\f
-/* Return the size of a string, including the null byte. */
+/* Return the size of a string, including the null byte.
+
+ This used to treat backslashes as escapes, and hence they were not included
+ in the count. However, that conflicts with what ASM_OUTPUT_ASCII does,
+ which treats a backslash as a backslash, escaping it if necessary, and hence
+ we must include them in the count. */
static unsigned long
size_of_string (str)
register char *str;
{
- register unsigned long size = 0;
- register unsigned long slen = strlen (str);
- register unsigned long i;
- register unsigned c;
-
- for (i = 0; i < slen; ++i)
- {
- c = str[i];
- if (c == '\\')
- ++i;
-
- size += 1;
- }
-
- /* Null terminator. */
- size += 1;
- return size;
+ return strlen (str) + 1;
}
/* Return the size of a location descriptor. */
case dw_val_class_lbl_id:
size += PTR_SIZE;
break;
- case dw_val_class_section_offset:
+ case dw_val_class_lbl_offset:
size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_str:
/* Prolog. */
size += size_of_line_prolog ();
- /* Set address register instruction. */
- size += size_of_set_address;
-
current_file = 1;
current_line = 1;
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
{
- register dw_line_info_ref line_info;
+ register dw_line_info_ref line_info = &line_info_table[lt_index];
+
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file)
+ continue;
/* Advance pc instruction. */
/* ??? See the DW_LNS_advance_pc comment in output_line_info. */
else
size += size_of_set_address;
- line_info = &line_info_table[lt_index];
if (line_info->dw_file_num != current_file)
{
/* Set file number instruction. */
{
register dw_separate_line_info_ref line_info
= &separate_line_info_table[lt_index];
+
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file
+ && line_info->function == function)
+ goto cont;
+
if (function != line_info->function)
{
function = line_info->function;
}
}
+ cont:
++lt_index;
/* If we're done with a function, end its sequence. */
return DW_FORM_data;
case dw_val_class_lbl_id:
return DW_FORM_addr;
- case dw_val_class_section_offset:
+ case dw_val_class_lbl_offset:
return DW_FORM_data;
case dw_val_class_str:
return DW_FORM_string;
fprintf (asm_out_file, "\t%s\t0,0\n", ASM_BYTE_OP);
}
+
+ /* Terminate the table. */
+ fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP);
}
/* Output location description stack opcode's operands (if any). */
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_debug_asm)
break;
case dw_val_class_float:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- a->dw_attr_val.v.val_float.length * 4);
- if (flag_debug_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_debug_asm)
- fprintf (asm_out_file, "\t%s fp constant word %d",
- ASM_COMMENT_START, i);
+ {
+ register unsigned int i;
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ a->dw_attr_val.v.val_float.length * 4);
+ if (flag_debug_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_debug_asm)
+ fprintf (asm_out_file, "\t%s fp constant word %u",
+ ASM_COMMENT_START, i);
- fputc ('\n', asm_out_file);
- }
+ 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);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, a->dw_attr_val.v.val_lbl_id);
break;
- case dw_val_class_section_offset:
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file,
- stripattributes
- (a->dw_attr_val.v.val_section));
+ case dw_val_class_lbl_offset:
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, a->dw_attr_val.v.val_lbl_id);
break;
case dw_val_class_str:
else
ASM_OUTPUT_ASCII (asm_out_file,
a->dw_attr_val.v.val_str,
- strlen (a->dw_attr_val.v.val_str) + 1);
+ (int) strlen (a->dw_attr_val.v.val_str) + 1);
break;
default:
fprintf (asm_out_file, "\t%s DWARF version number", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (ABBREV_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, abbrev_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section",
ASM_COMMENT_START);
of decl_printable_name for C++ looks like "A::f(int)". Let's drop the
argument list, and maybe the scope. */
-static char *
+static const char *
dwarf2_name (decl, scope)
tree decl;
int scope;
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_INFO_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
ASM_COMMENT_START);
}
else
{
- ASM_OUTPUT_ASCII (asm_out_file, pub->name, strlen (pub->name) + 1);
+ ASM_OUTPUT_ASCII (asm_out_file, pub->name,
+ (int) strlen (pub->name) + 1);
}
fputc ('\n', asm_out_file);
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_INFO_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
ASM_COMMENT_START);
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 4);
- if (PTR_SIZE == 8)
+ /* We need to align to twice the pointer size here.
+ If DWARF_OFFSET_SIZE == 4, then we have emitted 12 bytes, and need 4
+ bytes of padding to align for either 4 or 8 byte pointers. */
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
+ /* If DWARF_OFFSET_SIZE == 8, then we have emitted 20 bytes, and need 12
+ bytes of padding to align for 8 byte pointers. We have already emitted
+ 4 bytes of padding, so emit 8 more here. */
+ if (DWARF_OFFSET_SIZE == 8)
fprintf (asm_out_file, ",0,0");
if (flag_debug_asm)
ASM_COMMENT_START, 2 * PTR_SIZE);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, text_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label,
+ text_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
{
ASM_OUTPUT_ASCII (asm_out_file,
file_table[ft_index],
- strlen (file_table[ft_index]) + 1);
+ (int) strlen (file_table[ft_index]) + 1);
}
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
fputc ('\n', asm_out_file);
- /* Set the address register to the first location in the text section */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s DW_LNE_set_address", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- output_uleb128 (1 + PTR_SIZE);
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address);
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
- fputc ('\n', asm_out_file);
+ /* We used to set the address register to the first location in the text
+ section here, but that didn't accomplish anything since we already
+ have a line note for the opening brace of the first function. */
/* Generate the line number to PC correspondence table, encoded as
a series of state machine operations. */
current_file = 1;
current_line = 1;
- strcpy (prev_line_label, TEXT_SECTION);
+ strcpy (prev_line_label, text_section_label);
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
{
- register dw_line_info_ref line_info;
+ register dw_line_info_ref line_info = &line_info_table[lt_index];
+
+ /* Don't emit anything for redundant notes. Just updating the
+ address doesn't accomplish anything, because we already assume
+ that anything after the last address is this line. */
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file)
+ continue;
/* Emit debug info for the address of the current line, choosing
the encoding that uses the least amount of space. */
/* Emit debug info for the source file of the current line, if
different from the previous line. */
- line_info = &line_info_table[lt_index];
if (line_info->dw_file_num != current_file)
{
current_file = line_info->dw_file_num;
/* Emit debug info for the current line number, choosing the encoding
that uses the least amount of space. */
- line_offset = line_info->dw_line_num - current_line;
- line_delta = line_offset - DWARF_LINE_BASE;
- current_line = line_info->dw_line_num;
- if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+ if (line_info->dw_line_num != current_line)
{
- /* This can handle deltas from -10 to 234, using the current
- definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This
- takes 1 byte. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- DWARF_LINE_OPCODE_BASE + line_delta);
- if (flag_debug_asm)
- fprintf (asm_out_file,
- "\t%s line %ld", ASM_COMMENT_START, current_line);
+ line_offset = line_info->dw_line_num - current_line;
+ line_delta = line_offset - DWARF_LINE_BASE;
+ current_line = line_info->dw_line_num;
+ if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+ {
+ /* This can handle deltas from -10 to 234, using the current
+ definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This
+ takes 1 byte. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ DWARF_LINE_OPCODE_BASE + line_delta);
+ if (flag_debug_asm)
+ fprintf (asm_out_file,
+ "\t%s line %ld", ASM_COMMENT_START, current_line);
- fputc ('\n', asm_out_file);
+ fputc ('\n', asm_out_file);
+ }
+ else
+ {
+ /* This can handle any delta. This takes at least 4 bytes,
+ depending on the value being encoded. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s advance to line %ld",
+ ASM_COMMENT_START, current_line);
+
+ fputc ('\n', asm_out_file);
+ output_sleb128 (line_offset);
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+ }
}
else
{
- /* This can handle any delta. This takes at least 4 bytes, depending
- on the value being encoded. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s advance to line %ld",
- ASM_COMMENT_START, current_line);
-
- fputc ('\n', asm_out_file);
- output_sleb128 (line_offset);
- fputc ('\n', asm_out_file);
+ /* We still need to start a new row, so output a copy insn. */
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
}
register dw_separate_line_info_ref line_info
= &separate_line_info_table[lt_index];
+ /* Don't emit anything for redundant notes. */
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file
+ && line_info->function == function)
+ goto cont;
+
/* Emit debug info for the address of the current line. If this is
a new function, or the first line of a function, then we need
to handle it differently. */
output_sleb128 (line_offset);
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
}
+ else
+ {
+ /* We still need to start a new row, so output a copy insn. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+ }
+ cont:
++lt_index;
/* If we're done with a function, end its sequence. */
base_type_result = new_die (DW_TAG_base_type, comp_unit_die);
add_AT_string (base_type_result, DW_AT_name, type_name);
add_AT_unsigned (base_type_result, DW_AT_byte_size,
- TYPE_PRECISION (type) / BITS_PER_UNIT);
+ int_size_in_bytes (type));
add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
return base_type_result;
When creating memory location descriptors, we are effectively transforming
the RTL for a memory-resident object into its Dwarf postfix expression
equivalent. This routine recursively descends an RTL tree, turning
- it into Dwarf postfix code as it goes. */
+ it into Dwarf postfix code as it goes.
+
+ MODE is the mode of the memory reference, needed to handle some
+ autoincrement addressing modes. */
static dw_loc_descr_ref
-mem_loc_descriptor (rtl)
+mem_loc_descriptor (rtl, mode)
register rtx rtl;
+ enum machine_mode mode;
{
dw_loc_descr_ref mem_loc_result = NULL;
/* Note that for a dynamically sized array, the location we will generate a
switch (GET_CODE (rtl))
{
+ case POST_INC:
+ case POST_DEC:
+ /* POST_INC and POST_DEC can be handled just like a SUBREG. So we
+ just fall into the SUBREG code. */
+
+ /* ... fall through ... */
+
case SUBREG:
/* The case of a subreg may arise when we have a local (register)
variable or a formal (register) parameter which doesn't quite fill
break;
case MEM:
- mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0));
+ mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
break;
+ case LABEL_REF:
+ /* Some ports can transform a symbol ref into a label ref, because
+ the symbol ref is too far away and has to be dumped into a constant
+ pool. */
case CONST:
case SYMBOL_REF:
mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
mem_loc_result->dw_loc_oprnd1.v.val_addr = addr_to_string (rtl);
break;
+ case PRE_INC:
+ case PRE_DEC:
+ /* Turn these into a PLUS expression and fall into the PLUS code
+ below. */
+ rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0),
+ GEN_INT (GET_CODE (rtl) == PRE_INC
+ ? GET_MODE_UNIT_SIZE (mode)
+ : - GET_MODE_UNIT_SIZE (mode)));
+
+ /* ... fall through ... */
+
case PLUS:
if (is_based_loc (rtl))
mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
INTVAL (XEXP (rtl, 1)));
else
{
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0)));
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1)));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0),
+ mode));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1),
+ mode));
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0));
}
break;
case MULT:
/* If a pseudo-reg is optimized away, it is possible for it to
be replaced with a MEM containing a multiply. */
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0)));
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1)));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0), mode));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1), mode));
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
break;
break;
case MEM:
- loc_result = mem_loc_descriptor (XEXP (rtl, 0));
+ loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
break;
case CONCAT:
rtl = DECL_INCOMING_RTL (decl);
else if (! BYTES_BIG_ENDIAN
&& TREE_CODE (declared_type) == INTEGER_TYPE
- && TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
+ && (GET_MODE_SIZE (TYPE_MODE (declared_type))
+ <= GET_MODE_SIZE (TYPE_MODE (passed_type))))
rtl = DECL_INCOMING_RTL (decl);
}
+
+ /* If the parm was passed in registers, but lives on the stack, then
+ make a big endian correction if the mode of the type of the
+ parameter is not the same as the mode of the rtl. */
+ /* ??? This is the same series of checks that are made in dbxout.c before
+ we reach the big endian correction code there. It isn't clear if all
+ of these checks are necessary here, but keeping them all is the safe
+ thing to do. */
+ else if (GET_CODE (rtl) == MEM
+ && XEXP (rtl, 0) != const0_rtx
+ && ! CONSTANT_P (XEXP (rtl, 0))
+ /* Not passed in memory. */
+ && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM
+ /* Not passed by invisible reference. */
+ && (GET_CODE (XEXP (rtl, 0)) != REG
+ || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM
+ || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM
+#endif
+ )
+ /* Big endian correction check. */
+ && BYTES_BIG_ENDIAN
+ && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl)
+ && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
+ < UNITS_PER_WORD))
+ {
+ int offset = (UNITS_PER_WORD
+ - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
+ rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
+ plus_constant (XEXP (rtl, 0), offset));
+ }
}
if (rtl == NULL_RTX)
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (rtl);
#endif
static inline void
add_name_attribute (die, name_string)
register dw_die_ref die;
- register char *name_string;
+ register const char *name_string;
{
if (name_string != NULL && *name_string != 0)
add_AT_string (die, DW_AT_name, name_string);
rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound);
if (XEXP (loc, 0) != new_addr)
- loc = gen_rtx (MEM, GET_MODE (loc), new_addr);
+ loc = gen_rtx_MEM (GET_MODE (loc), new_addr);
}
add_AT_flag (decl_die, DW_AT_artificial, 1);
subtype. In such a case, we need to search the decl_scope_table to
find the parent of this subtype. */
- if (TREE_CODE_CLASS (TREE_CODE (scope)) == 't')
+ if (AGGREGATE_TYPE_P (scope))
containing_scope = TYPE_CONTEXT (scope);
else
containing_scope = NULL_TREE;
if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
containing_scope = NULL_TREE;
+ /* Ignore function type "scopes" from the C frontend. They mean that
+ a tagged type is local to a parmlist of a function declarator, but
+ that isn't useful to DWARF. */
+ if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE)
+ containing_scope = NULL_TREE;
+
/* Function-local tags and functions get stuck in limbo until they are
fixed up by decls_for_scope. */
if (context_die == NULL && containing_scope != NULL_TREE
if (i < 0)
{
- if (scope_die != comp_unit_die
- || TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't')
+ if (TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't')
abort ();
if (debug_info_level > DINFO_LEVEL_TERSE
&& !TREE_ASM_WRITTEN (containing_scope))
abort ();
+
+ /* If none of the current dies are suitable, we get file scope. */
+ scope_die = comp_unit_die;
}
}
}
}
+/* Remember a type in the incomplete_types_list. */
+
+static void
+add_incomplete_type (type)
+ tree type;
+{
+ if (incomplete_types == incomplete_types_allocated)
+ {
+ incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
+ incomplete_types_list
+ = (tree *) xrealloc (incomplete_types_list,
+ sizeof (tree) * incomplete_types_allocated);
+ }
+
+ incomplete_types_list[incomplete_types++] = type;
+}
+
+/* Walk through the list of incomplete types again, trying once more to
+ emit full debugging info for them. */
+
+static void
+retry_incomplete_types ()
+{
+ register tree type;
+
+ while (incomplete_types)
+ {
+ --incomplete_types;
+ type = incomplete_types_list[incomplete_types];
+ gen_type_die (type, comp_unit_die);
+ }
+}
+
/* Generate a DIE to represent an inlined instance of an enumeration type. */
static void
static void
gen_unspecified_parameters_die (decl_or_type, context_die)
- register tree decl_or_type;
+ register tree decl_or_type ATTRIBUTE_UNUSED;
register dw_die_ref context_die;
{
new_die (DW_TAG_unspecified_parameters, context_die);
= lookup_filename (DECL_SOURCE_FILE (decl));
if (get_AT_flag (old_die, DW_AT_declaration) != 1)
- abort ();
+ {
+ /* ??? This can happen if there is a bug in the program, for
+ instance, if it has duplicate function definitions. Ideally,
+ we should detect this case and ignore it. For now, if we have
+ already reported an error, any error at all, then assume that
+ we got here because of a input error, not a dwarf2 bug. */
+ if (errorcount)
+ return;
+ abort ();
+ }
/* If the definition comes from the same place as the declaration,
maybe use the old DIE. We always want the DIE for this function
|| context_die == NULL)
&& get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
&& (get_AT_unsigned (old_die, DW_AT_decl_line)
- == DECL_SOURCE_LINE (decl)))
+ == (unsigned)DECL_SOURCE_LINE (decl)))
{
subr_die = old_die;
if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
add_AT_unsigned (subr_die, DW_AT_decl_file, file_index);
if (get_AT_unsigned (old_die, DW_AT_decl_line)
- != DECL_SOURCE_LINE (decl))
+ != (unsigned)DECL_SOURCE_LINE (decl))
add_AT_unsigned
(subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
}
add_AT_unsigned (var_die, DW_AT_decl_file, file_index);
if (get_AT_unsigned (old_die, DW_AT_decl_line)
- != DECL_SOURCE_LINE (decl))
+ != (unsigned)DECL_SOURCE_LINE (decl))
add_AT_unsigned (var_die, DW_AT_decl_line,
DECL_SOURCE_LINE (decl));
else
{
insn = DECL_RTL (decl);
- if (GET_CODE (insn) == CODE_LABEL)
+
+ /* Deleted labels are programmer specified labels which have been
+ eliminated because of various optimisations. We still emit them
+ here so that it is possible to put breakpoints on them. */
+ if (GET_CODE (insn) == CODE_LABEL
+ || ((GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
{
/* When optimization is enabled (via -O) some parts of the compiler
(e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which
return;
if (TYPE_CONTEXT (type) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)))
nested = 1;
scope_die = scope_die_for (type, context_die);
}
}
else
- add_AT_flag (type_die, DW_AT_declaration, 1);
+ {
+ add_AT_flag (type_die, DW_AT_declaration, 1);
+
+ /* We can't do this for function-local types, and we don't need to. */
+ if (TREE_PERMANENT (type))
+ add_incomplete_type (type);
+ }
}
/* Generate a DIE for a subroutine _type_. */
/* If this is a nested type whose containing class hasn't been
written out yet, writing it out will cover this one, too. */
if (TYPE_CONTEXT (type)
- && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
{
gen_type_die (TYPE_CONTEXT (type), context_die);
gen_struct_or_union_type_die (type, context_die);
if (TYPE_CONTEXT (type)
- && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
pop_decl_scope ();
}
/* Generate all of the decls declared within a given scope and (recursively)
- all of it's sub-blocks. */
+ all of its sub-blocks. */
static void
decls_for_scope (stmt, context_die, depth)
if (DECL_IGNORED_P (decl))
{
if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl) != NULL)
+ && DECL_INITIAL (decl) != NULL)
abort ();
return;
static unsigned
lookup_filename (file_name)
- char *file_name;
+ const char *file_name;
{
static unsigned last_file_lookup_index = 0;
register unsigned i;
void
dwarf2out_line (filename, line)
- register char *filename;
+ register const char *filename;
register unsigned line;
{
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
function_section (current_function_decl);
- if (DECL_SECTION_NAME (current_function_decl))
+ if (DWARF2_ASM_LINE_DEBUG_INFO)
+ {
+ static const char *lastfile;
+
+ /* Emit the .file and .loc directives understood by GNU as. */
+ if (lastfile == 0 || strcmp (filename, lastfile))
+ {
+ fprintf (asm_out_file, "\t.file 0 \"%s\"\n", filename);
+ lastfile = filename;
+ }
+
+ fprintf (asm_out_file, "\t.loc 0 %d 0\n", line);
+
+ /* Indicate that line number info exists. */
+ ++line_info_table_in_use;
+
+ /* Indicate that multiple line number tables exist. */
+ if (DECL_SECTION_NAME (current_function_decl))
+ ++separate_line_info_table_in_use;
+ }
+ else if (DECL_SECTION_NAME (current_function_decl))
{
register dw_separate_line_info_ref line_info;
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL,
separate_line_info_table_in_use);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s line %d", ASM_COMMENT_START, line);
fputc ('\n', asm_out_file);
/* expand the line info table if necessary */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
line_info_table_in_use);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s line %d", ASM_COMMENT_START, line);
fputc ('\n', asm_out_file);
/* Expand the line info table if necessary. */
void
dwarf2out_start_source_file (filename)
- register char *filename ATTRIBUTE_UNUSED;
+ register const char *filename ATTRIBUTE_UNUSED;
{
}
void
dwarf2out_define (lineno, buffer)
- register unsigned lineno;
- register char *buffer;
+ register unsigned lineno ATTRIBUTE_UNUSED;
+ register const char *buffer ATTRIBUTE_UNUSED;
{
static int initialized = 0;
if (!initialized)
void
dwarf2out_undef (lineno, buffer)
register unsigned lineno ATTRIBUTE_UNUSED;
- register char *buffer ATTRIBUTE_UNUSED;
+ register const char *buffer ATTRIBUTE_UNUSED;
{
}
primary_filename = main_input_filename;
/* Allocate the initial hunk of the file_table. */
- file_table = (char **) xmalloc (FILE_TABLE_INCREMENT * sizeof (char *));
- bzero ((char *) file_table, FILE_TABLE_INCREMENT * sizeof (char *));
+ file_table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *));
file_table_allocated = FILE_TABLE_INCREMENT;
/* Skip the first entry - file numbers begin at 1. */
/* Allocate the initial hunk of the decl_die_table. */
decl_die_table
- = (dw_die_ref *) xmalloc (DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
- bzero ((char *) decl_die_table,
- DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
+ = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref));
decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
decl_die_table_in_use = 0;
/* Allocate the initial hunk of the decl_scope_table. */
decl_scope_table
- = (decl_scope_node *) xmalloc (DECL_SCOPE_TABLE_INCREMENT
- * sizeof (decl_scope_node));
- bzero ((char *) decl_scope_table,
- DECL_SCOPE_TABLE_INCREMENT * sizeof (decl_scope_node));
+ = (decl_scope_node *) xcalloc (DECL_SCOPE_TABLE_INCREMENT,
+ sizeof (decl_scope_node));
decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT;
decl_scope_depth = 0;
/* Allocate the initial hunk of the abbrev_die_table. */
abbrev_die_table
- = (dw_die_ref *) xmalloc (ABBREV_DIE_TABLE_INCREMENT
- * sizeof (dw_die_ref));
- bzero ((char *) abbrev_die_table,
- ABBREV_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
+ = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT,
+ sizeof (dw_die_ref));
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
abbrev_die_table_in_use = 1;
/* Allocate the initial hunk of the line_info_table. */
line_info_table
- = (dw_line_info_ref) xmalloc (LINE_INFO_TABLE_INCREMENT
- * sizeof (dw_line_info_entry));
- bzero ((char *) line_info_table,
- LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
+ = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
+ sizeof (dw_line_info_entry));
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
line_info_table_in_use = 1;
gen_compile_unit_die (main_input_filename);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0);
+ if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+ ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
+ else
+ strcpy (text_section_label, stripattributes (TEXT_SECTION));
+ ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
+ DEBUG_INFO_SECTION_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
+ DEBUG_LINE_SECTION_LABEL, 0);
+
+ ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
+ ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
+ if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+ ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
}
/* Output stuff that dwarf requires at the end of every file,
free (node);
}
+ /* Walk through the list of incomplete types again, trying once more to
+ emit full debugging info for them. */
+ retry_incomplete_types ();
+
/* Traverse the DIE tree and add sibling attributes to those DIE's
that have children. */
add_sibling_attributes (comp_unit_die);
/* Output the source line correspondence table. */
if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
{
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
- output_line_info ();
+ if (! DWARF2_ASM_LINE_DEBUG_INFO)
+ {
+ fputc ('\n', asm_out_file);
+ 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
was in .text. */
if (separate_line_info_table_in_use == 0)
{
- add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, TEXT_SECTION);
+ add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
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, DEBUG_LINE_SECTION);
+ add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list,
+ debug_line_section_label);
}
/* Output the abbreviation table. */