/* Output dbx-format symbol table information from GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "xcoffout.h"
#endif
+#undef DBXOUT_DECR_NESTING
+#define DBXOUT_DECR_NESTING \
+ if (--debug_nesting == 0 && symbol_queue_index > 0) \
+ { emit_pending_bincls_if_required (); debug_flush_symbol_queue (); }
+
+#undef DBXOUT_DECR_NESTING_AND_RETURN
+#define DBXOUT_DECR_NESTING_AND_RETURN(x) \
+ do {--debug_nesting; return (x);} while (0)
+
#ifndef ASM_STABS_OP
#define ASM_STABS_OP "\t.stabs\t"
#endif
#define STABS_GCC_MARKER "gcc2_compiled."
#endif
-/* Typical USG systems don't have stab.h, and they also have
- no use for DBX-format debugging info. */
-
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-
-/* Nonzero if we have actually used any of the GDB extensions
- to the debugging format. The idea is that we use them for the
- first time only if there's a strong reason, but once we have done that,
- we use them whenever convenient. */
-
-static int have_used_extensions = 0;
-
-/* Number for the next N_SOL filename stabs label. The number 0 is reserved
- for the N_SO filename stabs label. */
-
-#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
-static int source_label_number = 1;
-#endif
-
-#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT text_section ();
-#else
-#define FORCE_TEXT
-#endif
-
-#include "gstab.h"
-
-#define STAB_CODE_TYPE enum __stab_debug_code
-
-/* 1 if PARM is passed to this function in memory. */
-
-#define PARM_PASSED_IN_MEMORY(PARM) \
- (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
-
-/* A C expression for the integer offset value of an automatic variable
- (N_LSYM) having address X (an RTX). */
-#ifndef DEBUGGER_AUTO_OFFSET
-#define DEBUGGER_AUTO_OFFSET(X) \
- (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
-#endif
-
-/* A C expression for the integer offset value of an argument (N_PSYM)
- having address X (an RTX). The nominal offset is OFFSET. */
-#ifndef DEBUGGER_ARG_OFFSET
-#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
-#endif
-
-/* Stream for writing to assembler file. */
-
-static FILE *asmfile;
-
-/* Last source file name mentioned in a NOTE insn. */
-
-static const char *lastfile;
-
-/* Current working directory. */
-
-static const char *cwd;
-
enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
/* Structure recording information about a C data type.
The file_number and type_number elements are used if DBX_USE_BINCL
is defined. */
-struct typeinfo
+struct typeinfo GTY(())
{
enum typestatus status;
-#ifdef DBX_USE_BINCL
int file_number;
int type_number;
-#endif
};
/* Vector recording information about C data types.
we assign it a number using next_type_number.
That is its index in this vector. */
-struct typeinfo *typevec;
+static GTY ((length ("typevec_len"))) struct typeinfo *typevec;
/* Number of elements of space allocated in `typevec'. */
-static int typevec_len;
+static GTY(()) int typevec_len;
/* In dbx output, each type gets a unique number.
This is the number for the next type output.
The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field. */
-static int next_type_number;
+static GTY(()) int next_type_number;
-#ifdef DBX_USE_BINCL
+enum binclstatus {BINCL_NOT_REQUIRED, BINCL_PENDING, BINCL_PROCESSED};
/* When using N_BINCL in dbx output, each type number is actually a
pair of the file number and the type number within the file.
struct dbx_file *next;
int file_number;
int next_type_number;
+ enum binclstatus bincl_status; /* Keep track of lazy bincl. */
+ const char *pending_bincl_name; /* Name of bincl. */
+ struct dbx_file *prev; /* Chain to traverse all pending bincls. */
};
-/* This is the top of the stack. */
+/* This is the top of the stack.
+
+ This is not saved for PCH, because restoring a PCH should not change it.
+ next_file_number does have to be saved, because the PCH may use some
+ file numbers; however, just before restoring a PCH, next_file_number
+ should always be 0 because we should not have needed any file numbers
+ yet. */
+#ifdef DBX_USE_BINCL
static struct dbx_file *current_file;
+#endif
/* This is the next file number to use. */
-static int next_file_number;
+static GTY(()) int next_file_number;
+
+/* A counter for dbxout_function_end. */
+
+static GTY(()) int scope_labelno;
+
+/* A counter for dbxout_source_line. */
+
+static GTY(()) int dbxout_source_line_counter;
+
+/* Nonzero if we have actually used any of the GDB extensions
+ to the debugging format. The idea is that we use them for the
+ first time only if there's a strong reason, but once we have done that,
+ we use them whenever convenient. */
+
+static GTY(()) int have_used_extensions = 0;
+
+/* Number for the next N_SOL filename stabs label. The number 0 is reserved
+ for the N_SO filename stabs label. */
+
+static GTY(()) int source_label_number = 1;
+
+/* Last source file name mentioned in a NOTE insn. */
+
+static GTY(()) const char *lastfile;
+
+/* Used by PCH machinery to detect if 'lastfile' should be reset to
+ base_input_file. */
+static GTY(()) int lastfile_is_base;
+
+/* Typical USG systems don't have stab.h, and they also have
+ no use for DBX-format debugging info. */
+
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+
+#ifdef DBX_USE_BINCL
+/* If zero then there is no pending BINCL. */
+static int pending_bincls = 0;
+#endif
+
+/* The original input file name. */
+static const char *base_input_file;
+
+/* Current working directory. */
+
+static const char *cwd;
-#endif /* DBX_USE_BINCL */
+#ifdef DEBUG_SYMS_TEXT
+#define FORCE_TEXT function_section (current_function_decl);
+#else
+#define FORCE_TEXT
+#endif
+
+#include "gstab.h"
+
+#define STAB_CODE_TYPE enum __stab_debug_code
+
+/* 1 if PARM is passed to this function in memory. */
+
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+
+/* A C expression for the integer offset value of an automatic variable
+ (N_LSYM) having address X (an RTX). */
+#ifndef DEBUGGER_AUTO_OFFSET
+#define DEBUGGER_AUTO_OFFSET(X) \
+ (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#endif
+
+/* A C expression for the integer offset value of an argument (N_PSYM)
+ having address X (an RTX). The nominal offset is OFFSET. */
+#ifndef DEBUGGER_ARG_OFFSET
+#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
+#endif
+
+/* Stream for writing to assembler file. */
+
+static FILE *asmfile;
/* These variables are for dbxout_symbol to communicate to
dbxout_finish_symbol.
#define CONTIN do { } while (0)
#endif
-static void dbxout_init PARAMS ((const char *));
-static void dbxout_finish PARAMS ((const char *));
-static void dbxout_start_source_file PARAMS ((unsigned, const char *));
-static void dbxout_end_source_file PARAMS ((unsigned));
-static void dbxout_typedefs PARAMS ((tree));
-static void dbxout_type_index PARAMS ((tree));
+#ifdef DBX_USE_BINCL
+static void emit_bincl_stab (const char *c);
+static void emit_pending_bincls (void);
+#endif
+static inline void emit_pending_bincls_if_required (void);
+
+static void dbxout_init (const char *);
+static void dbxout_finish (const char *);
+static void dbxout_start_source_file (unsigned, const char *);
+static void dbxout_end_source_file (unsigned);
+static void dbxout_typedefs (tree);
+static void dbxout_type_index (tree);
#if DBX_CONTIN_LENGTH > 0
-static void dbxout_continue PARAMS ((void));
+static void dbxout_continue (void);
#endif
-static void dbxout_args PARAMS ((tree));
-static void dbxout_type_fields PARAMS ((tree));
-static void dbxout_type_method_1 PARAMS ((tree, const char *));
-static void dbxout_type_methods PARAMS ((tree));
-static void dbxout_range_type PARAMS ((tree));
-static void dbxout_type PARAMS ((tree, int));
-static void print_int_cst_octal PARAMS ((tree));
-static void print_octal PARAMS ((unsigned HOST_WIDE_INT, int));
-static void print_wide_int PARAMS ((HOST_WIDE_INT));
-static void dbxout_type_name PARAMS ((tree));
-static int dbxout_symbol_location PARAMS ((tree, tree, const char *, rtx));
-static void dbxout_symbol_name PARAMS ((tree, const char *, int));
-static void dbxout_prepare_symbol PARAMS ((tree));
-static void dbxout_finish_symbol PARAMS ((tree));
-static void dbxout_block PARAMS ((tree, int, tree));
-static void dbxout_global_decl PARAMS ((tree));
+static void dbxout_args (tree);
+static void dbxout_type_fields (tree);
+static void dbxout_type_method_1 (tree, const char *);
+static void dbxout_type_methods (tree);
+static void dbxout_range_type (tree);
+static void dbxout_type (tree, int);
+static bool print_int_cst_bounds_in_octal_p (tree);
+static void print_int_cst_octal (tree);
+static void print_octal (unsigned HOST_WIDE_INT, int);
+static void print_wide_int (HOST_WIDE_INT);
+static void dbxout_type_name (tree);
+static void dbxout_class_name_qualifiers (tree);
+static int dbxout_symbol_location (tree, tree, const char *, rtx);
+static void dbxout_symbol_name (tree, const char *, int);
+static void dbxout_prepare_symbol (tree);
+static void dbxout_finish_symbol (tree);
+static void dbxout_block (tree, int, tree);
+static void dbxout_global_decl (tree);
+static void dbxout_handle_pch (unsigned);
\f
/* The debug hooks structure. */
#if defined (DBX_DEBUGGING_INFO)
-static void dbxout_source_line PARAMS ((unsigned int, const char *));
-static void dbxout_source_file PARAMS ((FILE *, const char *));
-static void dbxout_function_end PARAMS ((void));
-static void dbxout_begin_function PARAMS ((tree));
-static void dbxout_begin_block PARAMS ((unsigned, unsigned));
-static void dbxout_end_block PARAMS ((unsigned, unsigned));
-static void dbxout_function_decl PARAMS ((tree));
+static void dbxout_source_line (unsigned int, const char *);
+static void dbxout_source_file (FILE *, const char *);
+static void dbxout_function_end (void);
+static void dbxout_begin_function (tree);
+static void dbxout_begin_block (unsigned, unsigned);
+static void dbxout_end_block (unsigned, unsigned);
+static void dbxout_function_decl (tree);
-struct gcc_debug_hooks dbx_debug_hooks =
+const struct gcc_debug_hooks dbx_debug_hooks =
{
dbxout_init,
dbxout_finish,
debug_true_tree, /* ignore_block */
dbxout_source_line, /* source_line */
dbxout_source_line, /* begin_prologue: just output line info */
- debug_nothing_int, /* end_prologue */
- debug_nothing_void, /* end_epilogue */
+ debug_nothing_int_charstar, /* end_prologue */
+ debug_nothing_int_charstar, /* end_epilogue */
#ifdef DBX_FUNCTION_FIRST
dbxout_begin_function,
#else
dbxout_global_decl, /* global_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
- debug_nothing_rtx /* label */
+ debug_nothing_rtx, /* label */
+ dbxout_handle_pch /* handle_pch */
};
#endif /* DBX_DEBUGGING_INFO */
#if defined (XCOFF_DEBUGGING_INFO)
-struct gcc_debug_hooks xcoff_debug_hooks =
+const struct gcc_debug_hooks xcoff_debug_hooks =
{
dbxout_init,
dbxout_finish,
debug_true_tree, /* ignore_block */
xcoffout_source_line,
xcoffout_begin_prologue, /* begin_prologue */
- debug_nothing_int, /* end_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
xcoffout_end_epilogue,
debug_nothing_tree, /* begin_function */
xcoffout_end_function,
dbxout_global_decl, /* global_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
- debug_nothing_rtx /* label */
+ debug_nothing_rtx, /* label */
+ dbxout_handle_pch /* handle_pch */
};
#endif /* XCOFF_DEBUGGING_INFO */
\f
#if defined (DBX_DEBUGGING_INFO)
static void
-dbxout_function_end ()
+dbxout_function_end (void)
{
- static int scope_labelno = 0;
char lscope_label_name[100];
/* Convert Ltext into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
labels. */
ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno);
- ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Lscope", scope_labelno);
+ (*targetm.asm_out.internal_label) (asmfile, "Lscope", scope_labelno);
scope_labelno++;
/* By convention, GCC will mark the end of a function with an N_FUN
symbol and an empty string. */
+#ifdef DBX_OUTPUT_NFUN
+ DBX_OUTPUT_NFUN (asmfile, lscope_label_name, current_function_decl);
+#else
fprintf (asmfile, "%s\"\",%d,0,0,", ASM_STABS_OP, N_FUN);
assemble_name (asmfile, lscope_label_name);
putc ('-', asmfile);
assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
fprintf (asmfile, "\n");
+#endif
}
#endif /* DBX_DEBUGGING_INFO */
Initialize `typevec' and output the standard data types of C. */
static void
-dbxout_init (input_file_name)
- const char *input_file_name;
+dbxout_init (const char *input_file_name)
{
char ltext_label_name[100];
- tree syms = getdecls ();
+ tree syms = (*lang_hooks.decls.getdecls) ();
asmfile = asm_out_file;
typevec_len = 100;
- typevec = (struct typeinfo *) xcalloc (typevec_len, sizeof typevec[0]);
+ typevec = ggc_calloc (typevec_len, sizeof typevec[0]);
/* Convert Ltext into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
/* Put the current working directory in an N_SO symbol. */
-#ifndef DBX_WORKING_DIRECTORY /* Only some versions of DBX want this,
- but GDB always does. */
if (use_gnu_debug_info_extensions)
-#endif
{
- if (!cwd && (cwd = getpwd ()) && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
+ if (!cwd && (cwd = get_src_pwd ())
+ && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
cwd = concat (cwd, FILE_NAME_JOINER, NULL);
if (cwd)
{
#else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
fprintf (asmfile, "%s", ASM_STABS_OP);
output_quoted_string (asmfile, cwd);
- fprintf (asmfile, ",%d,0,0,%s\n", N_SO, <ext_label_name[1]);
+ fprintf (asmfile, ",%d,0,0,", N_SO);
+ assemble_name (asmfile, ltext_label_name);
+ fputc ('\n', asmfile);
#endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
}
}
#ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
- /* This should NOT be DBX_OUTPUT_SOURCE_FILENAME. That
- would give us an N_SOL, and we want an N_SO. */
DBX_OUTPUT_MAIN_SOURCE_FILENAME (asmfile, input_file_name);
#else /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
/* We include outputting `Ltext:' here,
/* Used to put `Ltext:' before the reference, but that loses on sun 4. */
fprintf (asmfile, "%s", ASM_STABS_OP);
output_quoted_string (asmfile, input_file_name);
- fprintf (asmfile, ",%d,0,0,%s\n",
- N_SO, <ext_label_name[1]);
+ fprintf (asmfile, ",%d,0,0,", N_SO);
+ assemble_name (asmfile, ltext_label_name);
+ fputc ('\n', asmfile);
text_section ();
- ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", 0);
+ (*targetm.asm_out.internal_label) (asmfile, "Ltext", 0);
#endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
#ifdef DBX_OUTPUT_GCC_MARKER
ASM_STABS_OP, STABS_GCC_MARKER, N_OPT);
#endif
- lastfile = input_file_name;
+ base_input_file = lastfile = input_file_name;
next_type_number = 1;
#ifdef DBX_USE_BINCL
- current_file = (struct dbx_file *) xmalloc (sizeof *current_file);
+ current_file = xmalloc (sizeof *current_file);
current_file->next = NULL;
current_file->file_number = 0;
current_file->next_type_number = 1;
next_file_number = 1;
+ current_file->prev = NULL;
+ current_file->bincl_status = BINCL_NOT_REQUIRED;
+ current_file->pending_bincl_name = NULL;
#endif
/* Make sure that types `int' and `char' have numbers 1 and 2.
#ifdef DBX_OUTPUT_STANDARD_TYPES
DBX_OUTPUT_STANDARD_TYPES (syms);
-#else
- dbxout_symbol (TYPE_NAME (integer_type_node), 0);
- dbxout_symbol (TYPE_NAME (char_type_node), 0);
#endif
- /* Get all permanent types that have typedef names,
- and output them all, except for those already output. */
-
+ /* Get all permanent types that have typedef names, and output them
+ all, except for those already output. Some language front ends
+ put these declarations in the top-level scope; some do not. */
+ dbxout_typedefs ((*lang_hooks.decls.builtin_type_decls) ());
dbxout_typedefs (syms);
}
-/* Output any typedef names for types described by TYPE_DECLs in SYMS,
- in the reverse order from that which is found in SYMS. */
+/* Output any typedef names for types described by TYPE_DECLs in SYMS. */
static void
-dbxout_typedefs (syms)
- tree syms;
+dbxout_typedefs (tree syms)
{
- if (syms)
+ for (; syms != NULL_TREE; syms = TREE_CHAIN (syms))
{
- dbxout_typedefs (TREE_CHAIN (syms));
if (TREE_CODE (syms) == TYPE_DECL)
{
tree type = TREE_TYPE (syms);
if (TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && COMPLETE_TYPE_P (type)
+ && COMPLETE_OR_VOID_TYPE_P (type)
&& ! TREE_ASM_WRITTEN (TYPE_NAME (type)))
dbxout_symbol (TYPE_NAME (type), 0);
}
}
}
+#ifdef DBX_USE_BINCL
+/* Emit BINCL stab using given name. */
+static void
+emit_bincl_stab (const char *name)
+{
+ fprintf (asmfile, "%s", ASM_STABS_OP);
+ output_quoted_string (asmfile, name);
+ fprintf (asmfile, ",%d,0,0,0\n", N_BINCL);
+}
+
+/* If there are pending bincls then it is time to emit all of them. */
+
+static inline void
+emit_pending_bincls_if_required (void)
+{
+ if (pending_bincls)
+ emit_pending_bincls ();
+}
+
+/* Emit all pending bincls. */
+
+static void
+emit_pending_bincls (void)
+{
+ struct dbx_file *f = current_file;
+
+ /* Find first pending bincl. */
+ while (f->bincl_status == BINCL_PENDING)
+ f = f->next;
+
+ /* Now emit all bincls. */
+ f = f->prev;
+
+ while (f)
+ {
+ if (f->bincl_status == BINCL_PENDING)
+ {
+ emit_bincl_stab (f->pending_bincl_name);
+
+ /* Update file number and status. */
+ f->file_number = next_file_number++;
+ f->bincl_status = BINCL_PROCESSED;
+ }
+ if (f == current_file)
+ break;
+ f = f->prev;
+ }
+
+ /* All pending bincls have been emitted. */
+ pending_bincls = 0;
+}
+
+#else
+
+static inline void
+emit_pending_bincls_if_required (void) {}
+#endif
+
/* Change to reading from a new source file. Generate a N_BINCL stab. */
static void
-dbxout_start_source_file (line, filename)
- unsigned int line ATTRIBUTE_UNUSED;
- const char *filename ATTRIBUTE_UNUSED;
+dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
+ const char *filename ATTRIBUTE_UNUSED)
{
#ifdef DBX_USE_BINCL
- struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
+ struct dbx_file *n = xmalloc (sizeof *n);
n->next = current_file;
- n->file_number = next_file_number++;
n->next_type_number = 1;
+ /* Do not assign file number now.
+ Delay it until we actually emit BINCL. */
+ n->file_number = 0;
+ n->prev = NULL;
+ current_file->prev = n;
+ n->bincl_status = BINCL_PENDING;
+ n->pending_bincl_name = filename;
+ pending_bincls = 1;
current_file = n;
- fprintf (asmfile, "%s", ASM_STABS_OP);
- output_quoted_string (asmfile, filename);
- fprintf (asmfile, ",%d,0,0,0\n", N_BINCL);
#endif
}
/* Revert to reading a previous source file. Generate a N_EINCL stab. */
static void
-dbxout_end_source_file (line)
- unsigned int line ATTRIBUTE_UNUSED;
+dbxout_end_source_file (unsigned int line ATTRIBUTE_UNUSED)
{
#ifdef DBX_USE_BINCL
- struct dbx_file *next;
-
- fprintf (asmfile, "%s%d,0,0,0\n", ASM_STABN_OP, N_EINCL);
- next = current_file->next;
- free (current_file);
- current_file = next;
+ /* Emit EINCL stab only if BINCL is not pending. */
+ if (current_file->bincl_status == BINCL_PROCESSED)
+ fprintf (asmfile, "%s%d,0,0,0\n", ASM_STABN_OP, N_EINCL);
+ current_file->bincl_status = BINCL_NOT_REQUIRED;
+ current_file = current_file->next;
#endif
}
+/* Handle a few odd cases that occur when trying to make PCH files work. */
+
+static void
+dbxout_handle_pch (unsigned at_end)
+{
+ if (! at_end)
+ {
+ /* When using the PCH, this file will be included, so we need to output
+ a BINCL. */
+ dbxout_start_source_file (0, lastfile);
+
+ /* The base file when using the PCH won't be the same as
+ the base file when it's being generated. */
+ lastfile = NULL;
+ }
+ else
+ {
+ /* ... and an EINCL. */
+ dbxout_end_source_file (0);
+
+ /* Deal with cases where 'lastfile' was never actually changed. */
+ lastfile_is_base = lastfile == NULL;
+ }
+}
+
#if defined (DBX_DEBUGGING_INFO)
/* Output debugging info to FILE to switch to sourcefile FILENAME. */
static void
-dbxout_source_file (file, filename)
- FILE *file;
- const char *filename;
+dbxout_source_file (FILE *file, const char *filename)
{
+ if (lastfile == 0 && lastfile_is_base)
+ {
+ lastfile = base_input_file;
+ lastfile_is_base = 0;
+ }
+
if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
{
-#ifdef DBX_OUTPUT_SOURCE_FILENAME
- DBX_OUTPUT_SOURCE_FILENAME (file, filename);
-#else
char ltext_label_name[100];
ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext",
source_label_number);
fprintf (file, "%s", ASM_STABS_OP);
output_quoted_string (file, filename);
- fprintf (file, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]);
+ fprintf (asmfile, ",%d,0,0,", N_SOL);
+ assemble_name (asmfile, ltext_label_name);
+ fputc ('\n', asmfile);
if (current_function_decl != NULL_TREE
&& DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
; /* Don't change section amid function. */
else
text_section ();
- ASM_OUTPUT_INTERNAL_LABEL (file, "Ltext", source_label_number);
+ (*targetm.asm_out.internal_label) (file, "Ltext", source_label_number);
source_label_number++;
-#endif
lastfile = filename;
}
}
number LINENO. */
static void
-dbxout_source_line (lineno, filename)
- unsigned int lineno;
- const char *filename;
+dbxout_source_line (unsigned int lineno, const char *filename)
{
dbxout_source_file (asmfile, filename);
#ifdef ASM_OUTPUT_SOURCE_LINE
- ASM_OUTPUT_SOURCE_LINE (asmfile, lineno);
+ dbxout_source_line_counter += 1;
+ ASM_OUTPUT_SOURCE_LINE (asmfile, lineno, dbxout_source_line_counter);
#else
fprintf (asmfile, "%s%d,0,%d\n", ASM_STABD_OP, N_SLINE, lineno);
#endif
/* Describe the beginning of an internal block within a function. */
static void
-dbxout_begin_block (line, n)
- unsigned int line ATTRIBUTE_UNUSED;
- unsigned int n;
+dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
{
- ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBB", n);
+ emit_pending_bincls_if_required ();
+ (*targetm.asm_out.internal_label) (asmfile, "LBB", n);
}
/* Describe the end line-number of an internal block within a function. */
static void
-dbxout_end_block (line, n)
- unsigned int line ATTRIBUTE_UNUSED;
- unsigned int n;
+dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
{
- ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBE", n);
+ emit_pending_bincls_if_required ();
+ (*targetm.asm_out.internal_label) (asmfile, "LBE", n);
}
/* Output dbx data for a function definition.
(including all the auto variables of the function). */
static void
-dbxout_function_decl (decl)
- tree decl;
+dbxout_function_decl (tree decl)
{
+ emit_pending_bincls_if_required ();
#ifndef DBX_FUNCTION_FIRST
dbxout_begin_function (decl);
#endif
/* Debug information for a global DECL. Called from toplev.c after
compilation proper has finished. */
static void
-dbxout_global_decl (decl)
- tree decl;
+dbxout_global_decl (tree decl)
{
if (TREE_CODE (decl) == VAR_DECL
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL_SET_P (decl)) /* Not necessary? */
- dbxout_symbol (decl, 0);
-}
+ {
+ int saved_tree_used = TREE_USED (decl);
+ TREE_USED (decl) = 1;
+ dbxout_symbol (decl, 0);
+ TREE_USED (decl) = saved_tree_used;
+ }
+}
/* At the end of compilation, finish writing the symbol table.
Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is
to do nothing. */
static void
-dbxout_finish (filename)
- const char *filename ATTRIBUTE_UNUSED;
+dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
{
#ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END
DBX_OUTPUT_MAIN_SOURCE_FILE_END (asmfile, filename);
#endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */
+
+ debug_free_queue ();
}
/* Output the index of a type. */
static void
-dbxout_type_index (type)
- tree type;
+dbxout_type_index (tree type)
{
#ifndef DBX_USE_BINCL
fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
.stabs "...rest",code,0,value */
static void
-dbxout_continue ()
+dbxout_continue (void)
{
+ emit_pending_bincls_if_required ();
#ifdef DBX_CONTIN_CHAR
fprintf (asmfile, "%c", DBX_CONTIN_CHAR);
#else
recursive calls. */
static void
-dbxout_type_fields (type)
- tree type;
+dbxout_type_fields (tree type)
{
tree tem;
now. */
static void
-dbxout_type_method_1 (decl, debug_name)
- tree decl;
- const char *debug_name;
+dbxout_type_method_1 (tree decl, const char *debug_name)
{
char c1 = 'A', c2;
in TYPE. */
static void
-dbxout_type_methods (type)
- tree type;
+dbxout_type_methods (tree type)
{
/* C++: put out the method names and their parameter lists */
tree methods = TYPE_METHODS (type);
}
if (!need_prefix)
{
- putc (';', asmfile);
+ putc (';', asmfile);
CHARS (1);
}
}
TYPE is an INTEGER_TYPE. */
static void
-dbxout_range_type (type)
- tree type;
+dbxout_range_type (tree type)
{
fprintf (asmfile, "r");
if (TREE_TYPE (type))
{
putc (';', asmfile);
CHARS (1);
- print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
+ if (print_int_cst_bounds_in_octal_p (type))
+ print_int_cst_octal (TYPE_MIN_VALUE (type));
+ else
+ print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
}
else
{
{
putc (';', asmfile);
CHARS (1);
- print_wide_int (tree_low_cst (TYPE_MAX_VALUE (type), 0));
+ if (print_int_cst_bounds_in_octal_p (type))
+ print_int_cst_octal (TYPE_MAX_VALUE (type));
+ else
+ print_wide_int (tree_low_cst (TYPE_MAX_VALUE (type), 0));
putc (';', asmfile);
CHARS (1);
}
}
}
\f
+
/* Output a reference to a type. If the type has not yet been
described in the dbx output, output its definition now.
For a type already defined, just refer to its definition
using the number previously allocated. */
static void
-dbxout_type (type, full)
- tree type;
- int full;
+dbxout_type (tree type, int full)
{
tree tem;
+ tree main_variant;
static int anonymous_type_number = 0;
if (TREE_CODE (type) == VECTOR_TYPE)
- type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+ /* The frontend feeds us a representation for the vector as a struct
+ containing an array. Pull out the array type. */
+ type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
/* If there was an input error and we don't really have a type,
avoid crashing and write something that is at least valid
type = integer_type_node;
else
{
- /* Try to find the "main variant" with the same name but not const
- or volatile. (Since stabs does not distinguish const and volatile,
- there is no need to make them separate types. But types with
- different names are usefully distinguished.) */
-
- for (tem = TYPE_MAIN_VARIANT (type); tem; tem = TYPE_NEXT_VARIANT (tem))
- if (!TYPE_READONLY (tem) && !TYPE_VOLATILE (tem)
- && TYPE_NAME (tem) == TYPE_NAME (type))
- {
- type = tem;
- break;
- }
if (TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
full = 0;
}
+ /* Try to find the "main variant" with the same name. */
+ if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+ main_variant = TREE_TYPE (TYPE_NAME (type));
+ else
+ main_variant = TYPE_MAIN_VARIANT (type);
+
+ /* If we are not using extensions, stabs does not distinguish const and
+ volatile, so there is no need to make them separate types. */
+ if (!use_gnu_debug_info_extensions)
+ type = main_variant;
+
if (TYPE_SYMTAB_ADDRESS (type) == 0)
{
/* Type has no dbx number assigned. Assign next available number. */
if (next_type_number == typevec_len)
{
typevec
- = (struct typeinfo *) xrealloc (typevec,
- typevec_len * 2 * sizeof typevec[0]);
- memset ((char *) (typevec + typevec_len), 0,
- typevec_len * sizeof typevec[0]);
+ = ggc_realloc (typevec, (typevec_len * 2 * sizeof typevec[0]));
+ memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]);
typevec_len *= 2;
}
#ifdef DBX_USE_BINCL
+ emit_pending_bincls_if_required ();
typevec[TYPE_SYMTAB_ADDRESS (type)].file_number
= current_file->file_number;
typevec[TYPE_SYMTAB_ADDRESS (type)].type_number
#endif
}
+ if (flag_debug_only_used_symbols)
+ {
+ if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ && TYPE_STUB_DECL (type)
+ && TREE_CODE_CLASS (TREE_CODE (TYPE_STUB_DECL (type))) == 'd'
+ && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
+ debug_queue_symbol (TYPE_STUB_DECL (type));
+ else if (TYPE_NAME (type)
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+ debug_queue_symbol (TYPE_NAME (type));
+ }
+
/* Output the number of this type, to refer to it. */
dbxout_type_index (type);
typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED;
- if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
- {
+ /* If this type is a variant of some other, hand off. Types with
+ different names are usefully distinguished. We only distinguish
+ cv-qualified types if we're using extensions. */
+ if (TYPE_READONLY (type) > TYPE_READONLY (main_variant))
+ {
+ putc ('k', asmfile);
+ CHARS (1);
+ dbxout_type (build_type_variant (type, 0, TYPE_VOLATILE (type)), 0);
+ return;
+ }
+ else if (TYPE_VOLATILE (type) > TYPE_VOLATILE (main_variant))
+ {
+ putc ('B', asmfile);
+ CHARS (1);
+ dbxout_type (build_type_variant (type, TYPE_READONLY (type), 0), 0);
+ return;
+ }
+ else if (main_variant != TYPE_MAIN_VARIANT (type))
+ {
+ if (flag_debug_only_used_symbols)
+ {
+ tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
+ if ((TREE_CODE (orig_type) == RECORD_TYPE
+ || TREE_CODE (orig_type) == UNION_TYPE
+ || TREE_CODE (orig_type) == QUAL_UNION_TYPE
+ || TREE_CODE (orig_type) == ENUMERAL_TYPE)
+ && TYPE_STUB_DECL (orig_type)
+ && ! DECL_IGNORED_P (TYPE_STUB_DECL (orig_type)))
+ debug_queue_symbol (TYPE_STUB_DECL (orig_type));
+ }
+ /* 'type' is a typedef; output the type it refers to. */
dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0);
return;
}
+ /* else continue. */
switch (TREE_CODE (type))
{
write it as a subtype. */
else if (TREE_TYPE (type) != 0
&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
- dbxout_range_type (type);
+ {
+ /* If the size is non-standard, say what it is if we can use
+ GDB extensions. */
+
+ if (use_gnu_debug_info_extensions
+ && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
+ {
+ have_used_extensions = 1;
+ fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
+ CHARS (5);
+ }
+
+ dbxout_range_type (type);
+ }
else
- {
+ {
/* If the size is non-standard, say what it is if we can use
GDB extensions. */
CHARS (5);
}
- /* If we can use GDB extensions and the size is wider than a
- long (the size used by GDB to read them) or we may have
- trouble writing the bounds the usual way, write them in
- octal. Note the test is for the *target's* size of "long",
- not that of the host. The host test is just to make sure we
- can write it out in case the host wide int is narrower than the
- target "long". */
-
- /* For unsigned types, we use octal if they are the same size or
- larger. This is because we print the bounds as signed decimal,
- and hence they can't span same size unsigned types. */
-
- if (use_gnu_debug_info_extensions
- && TYPE_MIN_VALUE (type) != 0
- && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
- && TYPE_MAX_VALUE (type) != 0
- && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
- && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
- || ((TYPE_PRECISION (type)
- == TYPE_PRECISION (integer_type_node))
- && TREE_UNSIGNED (type))
- || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
- || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
- && TREE_UNSIGNED (type))))
+ if (print_int_cst_bounds_in_octal_p (type))
{
fprintf (asmfile, "r");
CHARS (1);
- dbxout_type_index (type);
+
+ /* If this type derives from another type, output type index of
+ parent type. This is particularly important when parent type
+ is an enumerated type, because not generating the parent type
+ index would transform the definition of this enumerated type
+ into a plain unsigned type. */
+ if (TREE_TYPE (type) != 0)
+ dbxout_type_index (TREE_TYPE (type));
+ else
+ dbxout_type_index (type);
+
fprintf (asmfile, ";");
CHARS (1);
print_int_cst_octal (TYPE_MIN_VALUE (type));
else
/* Output other integer types as subranges of `int'. */
dbxout_range_type (type);
- }
+ }
break;
break;
case COMPLEX_TYPE:
- /* Differs from the REAL_TYPE by its new data type number */
+ /* Differs from the REAL_TYPE by its new data type number.
+ R3 is NF_COMPLEX. We don't try to use any of the other NF_*
+ codes since gdb doesn't care anyway. */
if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
{
- fprintf (asmfile, "r");
- CHARS (1);
- dbxout_type_index (type);
- putc (';', asmfile);
- CHARS (1);
+ fputs ("R3;", asmfile);
+ CHARS (3);
print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
fputs (";0;", asmfile);
CHARS (3);
}
for (i = 0; i < n_baseclasses; i++)
{
- tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
+ tree binfo = TYPE_BINFO (type);
+ tree child = BINFO_BASETYPE (binfo, i);
+ tree access = (BINFO_BASEACCESSES (binfo)
+ ? BINFO_BASEACCESS (binfo, i) : access_public_node);
if (use_gnu_debug_info_extensions)
{
have_used_extensions = 1;
putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
- putc (TREE_VIA_PUBLIC (child) ? '2' : '0', asmfile);
+ putc (access == access_public_node ? '2' : '0', asmfile);
CHARS (2);
- if (TREE_VIA_VIRTUAL (child) && strcmp (lang_hooks.name, "GNU C++") == 0)
+ if (TREE_VIA_VIRTUAL (child)
+ && strcmp (lang_hooks.name, "GNU C++") == 0)
/* For a virtual base, print the (negative) offset within
the vtable where we must look to find the necessary
adjustment. */
* BITS_PER_UNIT);
putc (',', asmfile);
CHARS (1);
- print_wide_int (tree_low_cst (DECL_SIZE
- (TYPE_NAME
- (BINFO_TYPE (child))),
+ print_wide_int (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)),
0)
* BITS_PER_UNIT);
putc (';', asmfile);
CHARS (1);
return;
}
-#ifdef DBX_OUTPUT_ENUM
- DBX_OUTPUT_ENUM (asmfile, type);
-#else
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
putc (';', asmfile);
CHARS (1);
-#endif
break;
case POINTER_TYPE:
}
}
+/* Return nonzero if the given type represents an integer whose bounds
+ should be printed in octal format. */
+
+static bool
+print_int_cst_bounds_in_octal_p (tree type)
+{
+ /* If we can use GDB extensions and the size is wider than a long
+ (the size used by GDB to read them) or we may have trouble writing
+ the bounds the usual way, write them in octal. Note the test is for
+ the *target's* size of "long", not that of the host. The host test
+ is just to make sure we can write it out in case the host wide int
+ is narrower than the target "long".
+
+ For unsigned types, we use octal if they are the same size or larger.
+ This is because we print the bounds as signed decimal, and hence they
+ can't span same size unsigned types. */
+
+ if (use_gnu_debug_info_extensions
+ && TYPE_MIN_VALUE (type) != 0
+ && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
+ && TYPE_MAX_VALUE (type) != 0
+ && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
+ && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
+ || ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+ && TREE_UNSIGNED (type))
+ || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
+ || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
+ && TREE_UNSIGNED (type))))
+ return TRUE;
+ else
+ return FALSE;
+}
+
/* Print the value of integer constant C, in octal,
handling double precision. */
static void
-print_int_cst_octal (c)
- tree c;
+print_int_cst_octal (tree c)
{
unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c);
unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c);
}
static void
-print_octal (value, digits)
- unsigned HOST_WIDE_INT value;
- int digits;
+print_octal (unsigned HOST_WIDE_INT value, int digits)
{
int i;
/* Output C in decimal while adjusting the number of digits written. */
static void
-print_wide_int (c)
- HOST_WIDE_INT c;
+print_wide_int (HOST_WIDE_INT c)
{
int digs = 0;
CHARS (digs);
}
-
+
/* Output the name of type TYPE, with no punctuation.
Such names can be set up either by typedef declarations
or by struct, enum and union tags. */
static void
-dbxout_type_name (type)
- tree type;
+dbxout_type_name (tree type)
{
tree t;
if (TYPE_NAME (type) == 0)
fprintf (asmfile, "%s", IDENTIFIER_POINTER (t));
CHARS (IDENTIFIER_LENGTH (t));
}
+
+/* Output leading leading struct or class names needed for qualifying
+ type whose scope is limited to a struct or class. */
+
+static void
+dbxout_class_name_qualifiers (tree decl)
+{
+ tree context = decl_type_context (decl);
+
+ if (context != NULL_TREE
+ && TREE_CODE(context) == RECORD_TYPE
+ && TYPE_NAME (context) != 0
+ && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
+ || (DECL_NAME (TYPE_NAME (context)) != 0)))
+ {
+ tree name = TYPE_NAME (context);
+
+ emit_pending_bincls_if_required ();
+
+ if (TREE_CODE (name) == TYPE_DECL)
+ {
+ dbxout_class_name_qualifiers (name);
+ name = DECL_NAME (name);
+ }
+ fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
+ CHARS (IDENTIFIER_LENGTH (name) + 2);
+ }
+}
\f
/* Output a .stabs for the symbol defined by DECL,
which must be a ..._DECL node in the normal namespace.
Return 1 if a stabs might have been emitted. */
int
-dbxout_symbol (decl, local)
- tree decl;
- int local ATTRIBUTE_UNUSED;
+dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
{
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
int result = 0;
+ /* "Intercept" dbxout_symbol() calls like we do all debug_hooks. */
+ ++debug_nesting;
+
/* Cast avoids warning in old compilers. */
current_sym_code = (STAB_CODE_TYPE) 0;
current_sym_value = 0;
if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)
|| DECL_IGNORED_P (decl))
- return 0;
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
+
+ /* If we are to generate only the symbols actually used then such
+ symbol nodees are flagged with TREE_USED. Ignore any that
+ aren't flaged as TREE_USED. */
+
+ if (flag_debug_only_used_symbols)
+ {
+ tree t;
+
+ if (!TREE_USED (decl)
+ && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl)))
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
+
+ /* We now have a used symbol. We need to generate the info for
+ the symbol's type in addition to the symbol itself. These
+ type symbols are queued to be generated after were done with
+ the symbol itself (done because the symbol's info is generated
+ with fprintf's, etc. as it determines what's needed).
+
+ Note, because the TREE_TYPE(type) might be something like a
+ pointer to a named type we need to look for the first name
+ we see following the TREE_TYPE chain. */
+
+ t = type;
+ while (POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+
+ /* RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, and ENUMERAL_TYPE
+ need special treatment. The TYPE_STUB_DECL field in these
+ types generally represents the tag name type we want to
+ output. In addition there could be a typedef type with
+ a different name. In that case we also want to output
+ that. */
+
+ if ((TREE_CODE (t) == RECORD_TYPE
+ || TREE_CODE (t) == UNION_TYPE
+ || TREE_CODE (t) == QUAL_UNION_TYPE
+ || TREE_CODE (t) == ENUMERAL_TYPE)
+ && TYPE_STUB_DECL (t)
+ && TYPE_STUB_DECL (t) != decl
+ && TREE_CODE_CLASS (TREE_CODE (TYPE_STUB_DECL (t))) == 'd'
+ && ! DECL_IGNORED_P (TYPE_STUB_DECL (t)))
+ {
+ debug_queue_symbol (TYPE_STUB_DECL (t));
+ if (TYPE_NAME (t)
+ && TYPE_NAME (t) != TYPE_STUB_DECL (t)
+ && TYPE_NAME (t) != decl
+ && TREE_CODE_CLASS (TREE_CODE (TYPE_NAME (t))) == 'd')
+ debug_queue_symbol (TYPE_NAME (t));
+ }
+ else if (TYPE_NAME (t)
+ && TYPE_NAME (t) != decl
+ && TREE_CODE_CLASS (TREE_CODE (TYPE_NAME (t))) == 'd')
+ debug_queue_symbol (TYPE_NAME (t));
+ }
+
+ emit_pending_bincls_if_required ();
dbxout_prepare_symbol (decl);
case FUNCTION_DECL:
if (DECL_RTL (decl) == 0)
- return 0;
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
if (DECL_EXTERNAL (decl))
break;
/* Don't mention a nested function under its parent. */
break;
case TYPE_DECL:
-#if 0
- /* This seems all wrong. Outputting most kinds of types gives no name
- at all. A true definition gives no name; a cross-ref for a
- structure can give the tag name, but not a type name.
- It seems that no typedef name is defined by outputting a type. */
-
- /* If this typedef name was defined by outputting the type,
- don't duplicate it. */
- if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED
- && TYPE_NAME (TREE_TYPE (decl)) == decl)
- return 0;
-#endif
/* Don't output the same typedef twice.
And don't output what language-specific stuff doesn't want output. */
if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
- return 0;
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
FORCE_TEXT;
result = 1;
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
- && DECL_ARTIFICIAL (decl)
+ && DECL_ARTIFICIAL (decl)
+ /* Do not generate a tag for incomplete records. */
+ && COMPLETE_TYPE_P (type)
/* Do not generate a tag for records of variable size,
since this type can not be properly described in the
DBX format, and it confuses some tools such as objdump. */
dbxout_finish_symbol (NULL_TREE);
}
+ /* Output .stabs (or whatever) and leading double quote. */
+ fprintf (asmfile, "%s\"", ASM_STABS_OP);
+
+ if (use_gnu_debug_info_extensions)
+ {
+ /* Output leading class/struct qualifiers. */
+ dbxout_class_name_qualifiers (decl);
+ }
+
/* Output typedef name. */
- fprintf (asmfile, "%s\"%s:", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (decl)));
/* Short cut way to output a tag also. */
if ((TREE_CODE (type) == RECORD_TYPE
&& TYPE_NAME (type) == decl
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
- && DECL_ARTIFICIAL (decl))
+ && DECL_ARTIFICIAL (decl))
{
if (use_gnu_debug_info_extensions && have_used_extensions)
{
/* Named return value, treat like a VAR_DECL. */
case VAR_DECL:
if (! DECL_RTL_SET_P (decl))
- return 0;
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
/* Don't mention a variable that is external.
Let the file that defines it describe it. */
if (DECL_EXTERNAL (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
{
HOST_WIDE_INT ival = tree_low_cst (DECL_INITIAL (decl), 0);
-#ifdef DBX_OUTPUT_CONSTANT_SYMBOL
- DBX_OUTPUT_CONSTANT_SYMBOL (asmfile, name, ival);
-#else
- fprintf (asmfile, "%s\"%s:c=i", ASM_STABS_OP, name);
-
- fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, ival);
- fprintf (asmfile, "\",0x%x,0,0,0\n", N_LSYM);
-#endif
+ fprintf (asmfile, "%s\"%s:c=i" HOST_WIDE_INT_PRINT_DEC
+ "\",0x%x,0,0,0\n",
+ ASM_STABS_OP, name, ival, N_LSYM);
+ DBXOUT_DECR_NESTING;
return 1;
}
else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE)
result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
break;
-
+
default:
break;
}
+ DBXOUT_DECR_NESTING;
return result;
}
\f
Returns 1 if the stab was really emitted. */
static int
-dbxout_symbol_location (decl, type, suffix, home)
- tree decl, type;
- const char *suffix;
- rtx home;
+dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
{
int letter = 0;
int regno = -1;
+ emit_pending_bincls_if_required ();
+
/* Don't mention a variable at all
if it was completely optimized into nothingness.
-
+
If the decl was from an inline function, then its rtl
is not identically the rtl that was used in this
particular compilation. */
current_sym_code = DBX_STATIC_CONST_VAR_CODE;
else
{
+ /* 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. Alternatively, the symbol
+ in the constant pool might be referenced by a different
+ symbol. */
+ if (GET_CODE (current_sym_addr) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (current_sym_addr))
+ {
+ rtx tmp = get_pool_constant (current_sym_addr);
+
+ if (GET_CODE (tmp) == SYMBOL_REF
+ || GET_CODE (tmp) == LABEL_REF)
+ current_sym_addr = tmp;
+ }
+
/* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
data_section ();
Then output LETTER to indicate the kind of location the symbol has. */
static void
-dbxout_symbol_name (decl, suffix, letter)
- tree decl;
- const char *suffix;
- int letter;
+dbxout_symbol_name (tree decl, const char *suffix, int letter)
{
const char *name;
}
static void
-dbxout_prepare_symbol (decl)
- tree decl ATTRIBUTE_UNUSED;
+dbxout_prepare_symbol (tree decl ATTRIBUTE_UNUSED)
{
#ifdef WINNING_GDB
const char *filename = DECL_SOURCE_FILE (decl);
}
static void
-dbxout_finish_symbol (sym)
- tree sym;
+dbxout_finish_symbol (tree sym)
{
#ifdef DBX_FINISH_SYMBOL
DBX_FINISH_SYMBOL (sym);
#endif
}
-/* Output definitions of all the decls in a chain. Return non-zero if
+/* Output definitions of all the decls in a chain. Return nonzero if
anything was output */
int
-dbxout_syms (syms)
- tree syms;
+dbxout_syms (tree syms)
{
int result = 0;
while (syms)
of all the parms in PARMS, which is a chain of PARM_DECL nodes. */
void
-dbxout_parms (parms)
- tree parms;
+dbxout_parms (tree parms)
{
+ ++debug_nesting;
+
+ emit_pending_bincls_if_required ();
+
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
{
}
/* It is quite tempting to use:
-
+
dbxout_type (TREE_TYPE (parms), 0);
as the next statement, rather than using DECL_ARG_TYPE(), so
double on the stack, but if we emit a stab saying the type is a
float, then gdb will only read in a single value, and this will
produce an erroneous value. */
- dbxout_type (DECL_ARG_TYPE (parms), 0);
+ dbxout_type (DECL_ARG_TYPE (parms), 0);
current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
dbxout_finish_symbol (parms);
}
const char *const decl_name = (DECL_NAME (parms)
? IDENTIFIER_POINTER (DECL_NAME (parms))
: "(anon)");
- if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
- current_sym_value = 0;
+ if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
+ current_sym_value = 0;
else
current_sym_value
= INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
current_sym_addr = 0;
-
+ current_sym_code = N_PSYM;
+
FORCE_TEXT;
fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
+
+ current_sym_value
+ = DEBUGGER_ARG_OFFSET (current_sym_value,
+ XEXP (XEXP (DECL_RTL (parms), 0), 0));
dbxout_type (TREE_TYPE (parms), 0);
dbxout_finish_symbol (parms);
}
&& TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
&& GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
{
- current_sym_value +=
+ current_sym_value +=
GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
- GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)));
}
dbxout_finish_symbol (parms);
}
}
+ DBXOUT_DECR_NESTING;
}
/* Output definitions for the places where parms live during the function,
PARMS is a chain of PARM_DECL nodes. */
void
-dbxout_reg_parms (parms)
- tree parms;
+dbxout_reg_parms (tree parms)
{
+ ++debug_nesting;
+
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms))
{
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
}
+ DBXOUT_DECR_NESTING;
}
\f
/* Given a chain of ..._TYPE nodes (as come in a parameter list),
output definitions of those names, in raw form */
static void
-dbxout_args (args)
- tree args;
+dbxout_args (tree args)
{
while (args)
{
We handle them all in sequence. */
static void
-dbxout_block (block, depth, args)
- tree block;
- int depth;
- tree args;
+dbxout_block (tree block, int depth, tree args)
{
int blocknum = -1;
#if DBX_BLOCKS_FUNCTION_RELATIVE
- const char *begin_label;
+ const char *begin_label;
if (current_function_func_begin_label != NULL_TREE)
begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
else
{
int did_output;
-#ifdef DBX_LBRAC_FIRST
- did_output = 1;
-#else
/* In dbx format, the syms of a block come before the N_LBRAC.
If nothing is output, we don't need the N_LBRAC, either. */
did_output = 0;
did_output = dbxout_syms (BLOCK_VARS (block));
if (args)
dbxout_reg_parms (args);
-#endif
/* Now output an N_LBRAC symbol to represent the beginning of
the block. Use the block's tree-walk order to generate
tree decl = BLOCK_VARS (block);
while (decl)
{
-#ifdef DBX_OUTPUT_CATCH
- DBX_OUTPUT_CATCH (asmfile, decl, buf);
-#else
fprintf (asmfile, "%s\"%s:C1\",%d,0,0,", ASM_STABS_OP,
IDENTIFIER_POINTER (DECL_NAME (decl)), N_CATCH);
assemble_name (asmfile, buf);
fprintf (asmfile, "\n");
-#endif
decl = TREE_CHAIN (decl);
}
}
#endif
}
-#ifdef DBX_LBRAC_FIRST
- /* On some weird machines, the syms of a block
- come after the N_LBRAC. */
- if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
- dbxout_syms (BLOCK_VARS (block));
- if (args)
- dbxout_reg_parms (args);
-#endif
-
/* Output the subblocks. */
dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
#if defined (DBX_DEBUGGING_INFO)
static void
-dbxout_begin_function (decl)
- tree decl;
+dbxout_begin_function (tree decl)
{
- dbxout_symbol (decl, 0);
+ int saved_tree_used1 = TREE_USED (decl);
+ TREE_USED (decl) = 1;
+ if (DECL_NAME (DECL_RESULT (decl)) != 0)
+ {
+ int saved_tree_used2 = TREE_USED (DECL_RESULT (decl));
+ TREE_USED (DECL_RESULT (decl)) = 1;
+ dbxout_symbol (decl, 0);
+ TREE_USED (DECL_RESULT (decl)) = saved_tree_used2;
+ }
+ else
+ dbxout_symbol (decl, 0);
+ TREE_USED (decl) = saved_tree_used1;
+
dbxout_parms (DECL_ARGUMENTS (decl));
if (DECL_NAME (DECL_RESULT (decl)) != 0)
dbxout_symbol (DECL_RESULT (decl), 1);
#endif /* DBX_DEBUGGING_INFO */
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+#include "gt-dbxout.h"