OSDN Git Service

* config/xtensa/xtensa.c (xtensa_multibss_section_type_flags): Add
[pf3gnuchains/gcc-fork.git] / gcc / dbxout.c
index 73be0b0..d257729 100644 (file)
@@ -1,23 +1,23 @@
 /* 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 GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 /* Output dbx-format symbol table data.
@@ -70,6 +70,8 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "tree.h"
 #include "rtl.h"
@@ -82,11 +84,24 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "tm_p.h"
 #include "ggc.h"
+#include "debug.h"
+#include "function.h"
+#include "target.h"
+#include "langhooks.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #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
@@ -124,96 +139,13 @@ Boston, MA 02111-1307, USA.  */
 #define FILE_NAME_JOINER "/"
 #endif
 
-/* Nonzero means if the type has methods, only output debugging
-   information if methods are actually written to the asm file.  This
-   optimization only works if the debugger can detect the special C++
-   marker.  */
-
-#define MINIMAL_DEBUG 1
-
-#ifdef NO_DOLLAR_IN_LABEL
-#ifdef NO_DOT_IN_LABEL
-#undef MINIMAL_DEBUG
-#define MINIMAL_DEBUG 0
-#endif
-#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)
-
-static int flag_minimal_debug = MINIMAL_DEBUG;
-
-/* 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.  */
-
-static int source_label_number = 1;
-
-#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT text_section ();
-#else
-#define FORCE_TEXT
-#endif
-
-/* If there is a system stab.h, use it.  Otherwise, use our own.  */
-/* ??? This is supposed to describe the target's stab format, so using
-   the host HAVE_STAB_H appears to be wrong.  For now, we use our own file
-   when cross compiling.  */
-#if defined (USG) || !defined (HAVE_STAB_H) || defined (CROSS_COMPILE)
-#include "gstab.h" /* If doing DBX on sysV, use our own stab.h.  */
-#else
-#include <stab.h>
-
-/* This is a GNU extension we need to reference in this file.  */
-#ifndef N_CATCH
-#define N_CATCH 0x54
-#endif
-#endif
-
-#ifdef __GNU_STAB__
-#define STAB_CODE_TYPE enum __stab_debug_code
-#else
-#define STAB_CODE_TYPE int
-#endif
-
-/* 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)
+/* GDB needs to know that the stabs were generated by GCC.  We emit an
+   N_OPT stab at the beginning of the source file to indicate this.
+   The string is historical, and different on a very few targets.  */
+#ifndef STABS_GCC_MARKER
+#define STABS_GCC_MARKER "gcc2_compiled."
 #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.
@@ -223,13 +155,11 @@ enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
    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.
@@ -237,40 +167,118 @@ struct typeinfo
    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.
    This is a stack of input files.  */
 
-struct dbx_file
+struct dbx_file GTY(())
 {
   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.  */
 
-static struct dbx_file *current_file;
+static GTY(()) struct dbx_file *current_file;
 
 /* 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;
+
+#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.  */
 
-#endif /* DBX_USE_BINCL */
+static FILE *asmfile;
 
 /* These variables are for dbxout_symbol to communicate to
    dbxout_finish_symbol.
@@ -309,67 +317,149 @@ static int current_sym_nchars;
 #define CONTIN do { } while (0)
 #endif
 
-#if defined(ASM_OUTPUT_SECTION_NAME)
-static void dbxout_function_end                PARAMS ((void));
-#endif
-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_fptype_value (tree);
+static void dbxout_type_index (tree);
 #if DBX_CONTIN_LENGTH > 0
-static void dbxout_continue            PARAMS ((void));
-#endif
-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, int));
-static void print_int_cst_octal                PARAMS ((tree));
-static void print_octal                        PARAMS ((unsigned HOST_WIDE_INT, 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_really_begin_function PARAMS ((tree));
+static void dbxout_continue (void);
+#endif
+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
-#if defined(ASM_OUTPUT_SECTION_NAME)
+/* The debug hooks structure.  */
+#if defined (DBX_DEBUGGING_INFO)
+
+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);
+
+const struct gcc_debug_hooks dbx_debug_hooks =
+{
+  dbxout_init,
+  dbxout_finish,
+  debug_nothing_int_charstar,
+  debug_nothing_int_charstar,
+  dbxout_start_source_file,
+  dbxout_end_source_file,
+  dbxout_begin_block,
+  dbxout_end_block,
+  debug_true_tree,             /* ignore_block */
+  dbxout_source_line,          /* source_line */
+  dbxout_source_line,          /* begin_prologue: just output line info */
+  debug_nothing_int_charstar,  /* end_prologue */
+  debug_nothing_int_charstar,  /* end_epilogue */
+#ifdef DBX_FUNCTION_FIRST
+  dbxout_begin_function,
+#else
+  debug_nothing_tree,          /* begin_function */
+#endif
+  debug_nothing_int,           /* end_function */
+  dbxout_function_decl,
+  dbxout_global_decl,          /* global_decl */
+  debug_nothing_tree,          /* deferred_inline_function */
+  debug_nothing_tree,          /* outlining_inline_function */
+  debug_nothing_rtx,           /* label */
+  dbxout_handle_pch            /* handle_pch */
+};
+#endif /* DBX_DEBUGGING_INFO  */
+
+#if defined (XCOFF_DEBUGGING_INFO)
+const struct gcc_debug_hooks xcoff_debug_hooks =
+{
+  dbxout_init,
+  dbxout_finish,
+  debug_nothing_int_charstar,
+  debug_nothing_int_charstar,
+  dbxout_start_source_file,
+  dbxout_end_source_file,
+  xcoffout_begin_block,
+  xcoffout_end_block,
+  debug_true_tree,             /* ignore_block */
+  xcoffout_source_line,
+  xcoffout_begin_prologue,     /* begin_prologue */
+  debug_nothing_int_charstar,  /* end_prologue */
+  xcoffout_end_epilogue,
+  debug_nothing_tree,          /* begin_function */
+  xcoffout_end_function,
+  debug_nothing_tree,          /* function_decl */
+  dbxout_global_decl,          /* global_decl */
+  debug_nothing_tree,          /* deferred_inline_function */
+  debug_nothing_tree,          /* outlining_inline_function */
+  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);
-  fputc ('-', asmfile);
+  putc ('-', asmfile);
   assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
   fprintf (asmfile, "\n");
+#endif
 }
-#endif /* ! NO_DBX_FUNCTION_END */
+#endif /* DBX_DEBUGGING_INFO */
 
 /* At the beginning of compilation, start writing the symbol table.
    Initialize `typevec' and output the standard data types of C.  */
 
-void
-dbxout_init (asm_file, input_file_name, syms)
-     FILE *asm_file;
-     const char *input_file_name;
-     tree syms;
+static void
+dbxout_init (const char *input_file_name)
 {
   char ltext_label_name[100];
+  tree syms = (*lang_hooks.decls.getdecls) ();
 
-  asmfile = asm_file;
+  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
@@ -377,17 +467,11 @@ dbxout_init (asm_file, input_file_name, syms)
   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] != '/'))
-       {
-         char *wdslash = xmalloc (strlen (cwd) + sizeof (FILE_NAME_JOINER));
-         sprintf (wdslash, "%s%s", cwd, FILE_NAME_JOINER);
-         cwd = wdslash;
-       }
+      if (!cwd && (cwd = get_src_pwd ())
+         && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
+       cwd = concat (cwd, FILE_NAME_JOINER, NULL);
       if (cwd)
        {
 #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
@@ -395,14 +479,14 @@ dbxout_init (asm_file, input_file_name, syms)
 #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, &ltext_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,
@@ -410,29 +494,34 @@ dbxout_init (asm_file, input_file_name, syms)
   /* 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, &ltext_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 */
 
-  /* Possibly output something to inform GDB that this compilation was by
-     GCC.  It's easier for GDB to parse it when after the N_SO's.  This
-     is used in Solaris 2.  */
-#ifdef ASM_IDENTIFY_GCC_AFTER_SOURCE
-  ASM_IDENTIFY_GCC_AFTER_SOURCE (asmfile);
+#ifdef DBX_OUTPUT_GCC_MARKER
+  DBX_OUTPUT_GCC_MARKER (asmfile);
+#else
+  /* Emit an N_OPT stab to indicate that this file was compiled by GCC.  */
+  fprintf (asmfile, "%s\"%s\",%d,0,0,0\n",
+          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 = ggc_alloc (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.
@@ -444,9 +533,6 @@ dbxout_init (asm_file, input_file_name, syms)
 
 #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,
@@ -459,8 +545,7 @@ dbxout_init (asm_file, input_file_name, syms)
    in the reverse order from that which is found in SYMS.  */
 
 static void
-dbxout_typedefs (syms)
-     tree syms;
+dbxout_typedefs (tree syms)
 {
   if (syms)
     {
@@ -477,108 +562,309 @@ dbxout_typedefs (syms)
     }
 }
 
+#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.  */
 
-void
-dbxout_start_new_source_file (filename)
-     const char *filename ATTRIBUTE_UNUSED;
+static void
+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 = ggc_alloc (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.  */
 
-void
-dbxout_resume_previous_source_file ()
+static void
+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.  */
 
-void
-dbxout_source_file (file, filename)
-     FILE *file;
-     const char *filename;
+static void
+dbxout_source_file (FILE *file, const char *filename)
 {
-  char ltext_label_name[100];
+  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, &ltext_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;
     }
 }
 
-/* Output a line number symbol entry into output stream FILE, 
-   for source file FILENAME and line number LINENO.  */
+/* Output a line number symbol entry for source file FILENAME and line
+   number LINENO.  */
 
-void
-dbxout_source_line (file, filename, lineno)
-     FILE *file;
-     const char *filename;
-     int lineno;
+static void
+dbxout_source_line (unsigned int lineno, const char *filename)
 {
-  dbxout_source_file (file, filename);
+  dbxout_source_file (asmfile, filename);
 
 #ifdef ASM_OUTPUT_SOURCE_LINE
-  ASM_OUTPUT_SOURCE_LINE (file, lineno);
+  dbxout_source_line_counter += 1;
+  ASM_OUTPUT_SOURCE_LINE (asmfile, lineno, dbxout_source_line_counter);
 #else
-  fprintf (file, "%s%d,0,%d\n", ASM_STABD_OP, N_SLINE, lineno);
+  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 (unsigned int line ATTRIBUTE_UNUSED, unsigned int 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 (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
+{
+  emit_pending_bincls_if_required ();
+  (*targetm.asm_out.internal_label) (asmfile, "LBE", n);
+}
+
+/* Output dbx data for a function definition.
+   This includes a definition of the function name itself (a symbol),
+   definitions of the parameters (locating them in the parameter list)
+   and then output the block that makes up the function's body
+   (including all the auto variables of the function).  */
+
+static void
+dbxout_function_decl (tree decl)
+{
+  emit_pending_bincls_if_required ();
+#ifndef DBX_FUNCTION_FIRST
+  dbxout_begin_function (decl);
 #endif
+  dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
+#ifdef DBX_OUTPUT_FUNCTION_END
+  DBX_OUTPUT_FUNCTION_END (asmfile, decl);
+#endif
+  if (use_gnu_debug_info_extensions
+#if defined(NO_DBX_FUNCTION_END)
+      && ! NO_DBX_FUNCTION_END
+#endif
+      && targetm.have_named_sections)
+    dbxout_function_end ();
+}
+
+#endif /* DBX_DEBUGGING_INFO  */
+
+/* Debug information for a global DECL.  Called from toplev.c after
+   compilation proper has finished.  */
+static void
+dbxout_global_decl (tree decl)
+{
+  if (TREE_CODE (decl) == VAR_DECL
+      && ! DECL_EXTERNAL (decl)
+      && DECL_RTL_SET_P (decl))        /* Not necessary?  */
+    {
+      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.  */
 
-void
-dbxout_finish (file, filename)
-     FILE *file ATTRIBUTE_UNUSED;
-     const char *filename ATTRIBUTE_UNUSED;
+static void
+dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
 {
 #ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END
-  DBX_OUTPUT_MAIN_SOURCE_FILE_END (file, filename);
+  DBX_OUTPUT_MAIN_SOURCE_FILE_END (asmfile, filename);
 #endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */
+
+  debug_free_queue ();
+}
+
+/* Output floating point type values used by the 'R' stab letter.
+   These numbers come from include/aout/stab_gnu.h in binutils/gdb.
+
+   There are only 3 real/complex types defined, and we need 7/6.
+   We use NF_SINGLE as a generic float type, and NF_COMPLEX as a generic
+   complex type.  Since we have the type size anyways, we don't really need
+   to distinguish between different FP types, we only need to distinguish
+   between float and complex.  This works fine with gdb.
+
+   We only use this for complex types, to avoid breaking backwards
+   compatibility for real types.  complex types aren't in ISO C90, so it is
+   OK if old debuggers don't understand the debug info we emit for them.  */
+
+/* ??? These are supposed to be IEEE types, but we don't check for that.
+   We could perhaps add additional numbers for non-IEEE types if we need
+   them.  */
+
+static void
+dbxout_fptype_value (tree type)
+{
+  char value = '0';
+  enum machine_mode mode = TYPE_MODE (type);
+
+  if (TREE_CODE (type) == REAL_TYPE)
+    {
+      if (mode == SFmode)
+       value = '1';
+      else if (mode == DFmode)
+       value = '2';
+      else if (mode == TFmode || mode == XFmode)
+       value = '6';
+      else
+       /* Use NF_SINGLE as a generic real type for other sizes.  */
+       value = '1';
+    }
+  else if (TREE_CODE (type) == COMPLEX_TYPE)
+    {
+      if (mode == SCmode)
+       value = '3';
+      else if (mode == DCmode)
+       value = '4';
+      else if (mode == TCmode || mode == XCmode)
+       value = '5';
+      else
+       /* Use NF_COMPLEX as a generic complex type for other sizes.  */
+       value = '3';
+    }
+  else
+    abort ();
+
+  putc (value, asmfile);
+  CHARS (1);
 }
 
 /* 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));
@@ -586,7 +872,7 @@ dbxout_type_index (type)
 #else
   struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)];
   fprintf (asmfile, "(%d,%d)", t->file_number, t->type_number);
-  CHARS (7);
+  CHARS (9);
 #endif
 }
 
@@ -598,8 +884,9 @@ dbxout_type_index (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
@@ -616,8 +903,7 @@ dbxout_continue ()
    recursive calls.  */
 
 static void
-dbxout_type_fields (type)
-     tree type;
+dbxout_type_fields (tree type)
 {
   tree tem;
 
@@ -644,25 +930,6 @@ dbxout_type_fields (type)
          if (tem != TYPE_FIELDS (type))
            CONTIN;
 
-         if (use_gnu_debug_info_extensions
-             && flag_minimal_debug
-             && TREE_CODE (tem) == FIELD_DECL
-             && DECL_VIRTUAL_P (tem)
-             && DECL_ASSEMBLER_NAME (tem))
-           {
-             have_used_extensions = 1;
-             CHARS (3 + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (tem)));
-             fputs (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)), asmfile);
-             dbxout_type (DECL_FCONTEXT (tem), 0, 0);
-             fprintf (asmfile, ":");
-             dbxout_type (TREE_TYPE (tem), 0, 0);
-             fputc (',', asmfile);
-             fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                      int_bit_position (tem));
-             fputc (';', asmfile);
-             continue;
-           }
-
          if (DECL_NAME (tem))
            {
              fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
@@ -671,7 +938,7 @@ dbxout_type_fields (type)
          else
            {
              fprintf (asmfile, ":");
-             CHARS (2);
+             CHARS (1);
            }
 
          if (use_gnu_debug_info_extensions
@@ -688,32 +955,33 @@ dbxout_type_fields (type)
 
          dbxout_type ((TREE_CODE (tem) == FIELD_DECL
                        && DECL_BIT_FIELD_TYPE (tem))
-                      ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0, 0);
+                      ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0);
 
          if (TREE_CODE (tem) == VAR_DECL)
            {
              if (TREE_STATIC (tem) && use_gnu_debug_info_extensions)
                {
-                 const char *name =
-                   IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem));
+                 tree name = DECL_ASSEMBLER_NAME (tem);
+
                  have_used_extensions = 1;
-                 fprintf (asmfile, ":%s;", name);
-                 CHARS (strlen (name));
+                 fprintf (asmfile, ":%s;", IDENTIFIER_POINTER (name));
+                 CHARS (IDENTIFIER_LENGTH (name) + 2);
                }
              else
-               /* If TEM is non-static, GDB won't understand it.  */
-               fprintf (asmfile, ",0,0;");
+               {
+                 /* If TEM is non-static, GDB won't understand it.  */
+                 fprintf (asmfile, ",0,0;");
+                 CHARS (5);
+               }
            }
          else
            {
-             fputc (',', asmfile);
-             fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                      int_bit_position (tem));
-             fputc (',', asmfile);
-             fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                      tree_low_cst (DECL_SIZE (tem), 1));
-             fputc (';', asmfile);
-             CHARS (23);
+             putc (',', asmfile);
+             print_wide_int (int_bit_position (tem));
+             putc (',', asmfile);
+             print_wide_int (tree_low_cst (DECL_SIZE (tem), 1));
+             putc (';', asmfile);
+             CHARS (3);
            }
        }
     }
@@ -725,9 +993,7 @@ dbxout_type_fields (type)
    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;
 
@@ -759,12 +1025,12 @@ dbxout_type_method_1 (decl, debug_name)
 
   if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0))
     {
-      fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-              tree_low_cst (DECL_VINDEX (decl), 0));
-      fputc (';', asmfile);
-      dbxout_type (DECL_CONTEXT (decl), 0, 0);
+      print_wide_int (tree_low_cst (DECL_VINDEX (decl), 0));
+      putc (';', asmfile);
+      CHARS (1);
+      dbxout_type (DECL_CONTEXT (decl), 0);
       fprintf (asmfile, ";");
-      CHARS (8);
+      CHARS (1);
     }
 }
 \f
@@ -772,16 +1038,15 @@ dbxout_type_method_1 (decl, debug_name)
    in TYPE.  */
 
 static void
-dbxout_type_methods (type)
-     register tree type;
+dbxout_type_methods (tree type)
 {
   /* C++: put out the method names and their parameter lists */
   tree methods = TYPE_METHODS (type);
   tree type_encoding;
-  register tree fndecl;
-  register tree last;
+  tree fndecl;
+  tree last;
   char formatted_type_identifier_length[16];
-  register int type_identifier_length;
+  int type_identifier_length;
 
   if (methods == NULL_TREE)
     return;
@@ -808,7 +1073,7 @@ dbxout_type_methods (type)
 
   type_identifier_length = IDENTIFIER_LENGTH (type_encoding);
 
-  sprintf(formatted_type_identifier_length, "%d", type_identifier_length);
+  sprintf (formatted_type_identifier_length, "%d", type_identifier_length);
 
   if (TREE_CODE (methods) != TREE_VEC)
     fndecl = methods;
@@ -819,7 +1084,6 @@ dbxout_type_methods (type)
 
   while (fndecl)
     {
-      tree name = DECL_NAME (fndecl);
       int need_prefix = 1;
 
       /* Group together all the methods for the same operation.
@@ -833,9 +1097,15 @@ dbxout_type_methods (type)
        {
          /* This is the "mangled" name of the method.
             It encodes the argument types.  */
-         const char *debug_name =
-           IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
-         int show_arg_types = 0;
+         const char *debug_name;
+
+         /* Skip methods that aren't FUNCTION_DECLs.  (In C++, these
+            include TEMPLATE_DECLs.)  The debugger doesn't know what
+            to do with such entities anyhow.  */
+         if (TREE_CODE (fndecl) != FUNCTION_DECL)
+           continue;
+
+         debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
 
          CONTIN;
 
@@ -846,80 +1116,23 @@ dbxout_type_methods (type)
          if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl))
            continue;
 
-         if (flag_minimal_debug)
+         /* Redundantly output the plain name, since that's what gdb
+            expects.  */
+         if (need_prefix)
            {
-             char marker;
-
-             /* We can't optimize a method which uses an anonymous
-                 class, because the debugger will not be able to
-                 associate the arbitrary class name with the actual
-                 class.  */
-#ifndef NO_DOLLAR_IN_LABEL
-             marker = '$';
-#else
-             marker = '.';
-#endif
-             if (strchr (debug_name, marker))
-               show_arg_types = 1;
-             /* Detect ordinary methods because their mangled names
-                start with the operation name.  */
-             else if (!strncmp (IDENTIFIER_POINTER (name), debug_name,
-                                IDENTIFIER_LENGTH (name)))
-               {
-                 debug_name += IDENTIFIER_LENGTH (name);
-                 if (debug_name[0] == '_' && debug_name[1] == '_')
-                   {
-                     const char *method_name = debug_name + 2;
-                     const char *length_ptr =
-                       formatted_type_identifier_length;
-                     /* Get past const and volatile qualifiers.  */
-                     while (*method_name == 'C' || *method_name == 'V')
-                       method_name++;
-                     /* Skip digits for length of type_encoding.  */
-                     while (*method_name == *length_ptr && *length_ptr)
-                         length_ptr++, method_name++;
-                     if (! strncmp (method_name,
-                                    IDENTIFIER_POINTER (type_encoding),
-                                    type_identifier_length))
-                       method_name += type_identifier_length;
-                     debug_name = method_name;
-                   }
-               }
-             /* Detect constructors by their style of name mangling.  */
-             else if (debug_name[0] == '_' && debug_name[1] == '_')
-               {
-                 const char *ctor_name = debug_name + 2;
-                 const char *length_ptr = formatted_type_identifier_length;
-                 while (*ctor_name == 'C' || *ctor_name == 'V')
-                   ctor_name++;
-                 /* Skip digits for length of type_encoding.  */
-                 while (*ctor_name == *length_ptr && *length_ptr)
-                     length_ptr++, ctor_name++;
-                 if (!strncmp (IDENTIFIER_POINTER (type_encoding), ctor_name,
-                               type_identifier_length))
-                   debug_name = ctor_name + type_identifier_length;
-               }
-             /* The other alternative is a destructor.  */
-             else
-               show_arg_types = 1;
-
-             /* Output the operation name just once, for the first method
-                that we output.  */
-             if (need_prefix)
-               {
-                 fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
-                 CHARS (IDENTIFIER_LENGTH (name) + 2);
-                 need_prefix = 0;
-               }
+             tree name = DECL_NAME (fndecl);
+             fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
+             CHARS (IDENTIFIER_LENGTH (name) + 2);
+             need_prefix = 0;
            }
 
-         dbxout_type (TREE_TYPE (fndecl), 0, show_arg_types);
+         dbxout_type (TREE_TYPE (fndecl), 0);
 
          dbxout_type_method_1 (fndecl, debug_name);
        }
       if (!need_prefix)
        {
-          putc (';', asmfile);
+         putc (';', asmfile);
          CHARS (1);
        }
     }
@@ -930,14 +1143,13 @@ dbxout_type_methods (type)
    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))
-    dbxout_type (TREE_TYPE (type), 0, 0);
+    dbxout_type (TREE_TYPE (type), 0);
   else if (TREE_CODE (type) != INTEGER_TYPE)
-    dbxout_type (type, 0, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
+    dbxout_type (type, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
   else
     {
       /* Traditionally, we made sure 'int' was type 1, and builtin types
@@ -961,25 +1173,39 @@ dbxout_range_type (type)
   if (TYPE_MIN_VALUE (type) != 0
       && host_integerp (TYPE_MIN_VALUE (type), 0))
     {
-      fputc (';', asmfile);
-      fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-              tree_low_cst (TYPE_MIN_VALUE (type), 0));
+      putc (';', asmfile);
+      CHARS (1);
+      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
-    fprintf (asmfile, ";0");
+    {
+      fprintf (asmfile, ";0");
+      CHARS (2);
+    }
 
   if (TYPE_MAX_VALUE (type) != 0
       && host_integerp (TYPE_MAX_VALUE (type), 0))
     {
-      fputc (';', asmfile);
-      fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-              tree_low_cst (TYPE_MAX_VALUE (type), 0));
-      fputc (';', asmfile);
+      putc (';', asmfile);
+      CHARS (1);
+      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);
     }
   else
-    fprintf (asmfile, ";-1;");
+    {
+      fprintf (asmfile, ";-1;");
+      CHARS (4);
+    }
 }
 \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
@@ -988,22 +1214,19 @@ dbxout_range_type (type)
    If FULL is nonzero, and the type has been described only with
    a forward-reference, output the definition now.
    If FULL is zero in this case, just refer to the forward-reference
-   using the number previously allocated.
-
-   If SHOW_ARG_TYPES is nonzero, we output a description of the argument
-   types for a METHOD_TYPE.  */
+   using the number previously allocated.  */
 
 static void
-dbxout_type (type, full, show_arg_types)
-     tree type;
-     int full;
-     int show_arg_types;
+dbxout_type (tree type, int full)
 {
-  register tree tem;
+  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
@@ -1012,24 +1235,24 @@ dbxout_type (type, full, show_arg_types)
     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.  */
@@ -1040,14 +1263,13 @@ dbxout_type (type, full, show_arg_types)
       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
@@ -1055,6 +1277,21 @@ dbxout_type (type, full, show_arg_types)
 #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);
 
@@ -1077,7 +1314,7 @@ dbxout_type (type, full, show_arg_types)
         Sun dbx crashes if we do.  */
       if (! full || !COMPLETE_TYPE_P (type)
          /* No way in DBX fmt to describe a variable size.  */
-         || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+         || ! host_integerp (TYPE_SIZE (type), 1))
        return;
       break;
     case TYPE_DEFINED:
@@ -1102,7 +1339,7 @@ dbxout_type (type, full, show_arg_types)
         && !full)
        || !COMPLETE_TYPE_P (type)
        /* No way in DBX fmt to describe a variable size.  */
-       || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+       || ! host_integerp (TYPE_SIZE (type), 1))
       {
        typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
        return;
@@ -1119,12 +1356,42 @@ dbxout_type (type, full, show_arg_types)
 
   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)))
-    { 
-      dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0, 0);
+  /* 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))
     {
@@ -1147,113 +1414,132 @@ dbxout_type (type, full, show_arg_types)
             This used to use `r2' explicitly and we used to
             take care to make sure that `char' was type number 2.  */
          fprintf (asmfile, "r");
+         CHARS (1);
          dbxout_type_index (type);
          fprintf (asmfile, ";0;127;");
+         CHARS (7);
        }
 
       /* If this is a subtype of another integer type, always prefer to
         write it as a subtype.  */
       else if (TREE_TYPE (type) != 0
-              && TREE_CODE (TREE_TYPE (type)) == INTEGER_CST)
-       dbxout_range_type (type);
+              && TREE_CODE (TREE_TYPE (type)) == INTEGER_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.  */
 
          if (use_gnu_debug_info_extensions
              && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
-           fprintf (asmfile, "@s%d;", TYPE_PRECISION (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))))
+           {
+             have_used_extensions = 1;
+             fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
+             CHARS (5);
+           }
+
+         if (print_int_cst_bounds_in_octal_p (type))
            {
              fprintf (asmfile, "r");
-             dbxout_type_index (type);
+             CHARS (1);
+
+              /* 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));
              fprintf (asmfile, ";");
+             CHARS (1);
              print_int_cst_octal (TYPE_MAX_VALUE (type));
              fprintf (asmfile, ";");
+             CHARS (1);
            }
 
          else
            /* Output other integer types as subranges of `int'.  */
            dbxout_range_type (type);
-       }
+       }
 
-      CHARS (22);
       break;
 
     case REAL_TYPE:
       /* This used to say `r1' and we used to take care
         to make sure that `int' was type number 1.  */
       fprintf (asmfile, "r");
+      CHARS (1);
       dbxout_type_index (integer_type_node);
-      fputc (';', asmfile);
-      fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, int_size_in_bytes (type));
+      putc (';', asmfile);
+      CHARS (1);
+      print_wide_int (int_size_in_bytes (type));
       fputs (";0;", asmfile);
-      CHARS (13);
+      CHARS (3);
       break;
 
     case CHAR_TYPE:
       if (use_gnu_debug_info_extensions)
        {
+         have_used_extensions = 1;
          fputs ("@s", asmfile);
-         fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                  BITS_PER_UNIT * int_size_in_bytes (type));
+         CHARS (2);
+         print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
          fputs (";-20;", asmfile);
+         CHARS (4);
        }
       else
        {
          /* Output the type `char' as a subrange of itself.
             That is what pcc seems to do.  */
          fprintf (asmfile, "r");
+         CHARS (1);
          dbxout_type_index (char_type_node);
          fprintf (asmfile, ";0;%d;", TREE_UNSIGNED (type) ? 255 : 127);
+         CHARS (7);
        }
-      CHARS (9);
       break;
 
     case BOOLEAN_TYPE:
       if (use_gnu_debug_info_extensions)
        {
+         have_used_extensions = 1;
          fputs ("@s", asmfile);
-         fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                  BITS_PER_UNIT * int_size_in_bytes (type));
+         CHARS (2);
+         print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
          fputs (";-16;", asmfile);
+         CHARS (4);
        }
       else /* Define as enumeral type (False, True) */
-       fprintf (asmfile, "eFalse:0,True:1,;");
-      CHARS (17);
+       {
+         fprintf (asmfile, "eFalse:0,True:1,;");
+         CHARS (17);
+       }
       break;
 
     case FILE_TYPE:
       putc ('d', asmfile);
       CHARS (1);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case COMPLEX_TYPE:
@@ -1261,34 +1547,34 @@ dbxout_type (type, full, show_arg_types)
 
       if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
        {
-         fprintf (asmfile, "r");
-         dbxout_type_index (type);
-         fputc (';', asmfile);
-         fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                  2 * int_size_in_bytes (TREE_TYPE (type)));
+         putc ('R', asmfile);
+         CHARS (1);
+         dbxout_fptype_value (type);
+         putc (';', asmfile);
+         CHARS (1);
+         print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
          fputs (";0;", asmfile);
-         CHARS (12);           /* The number is probably incorrect here.  */
+         CHARS (3);
        }
       else
        {
          /* Output a complex integer type as a structure,
             pending some other way to do it.  */
-         fputc ('s', asmfile);
-         fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, int_size_in_bytes (type));
-
+         putc ('s', asmfile);
+         CHARS (1);
+         print_wide_int (int_size_in_bytes (type));
          fprintf (asmfile, "real:");
-         CHARS (10);
-         dbxout_type (TREE_TYPE (type), 0, 0);
-         fprintf (asmfile, ",%d,%d;",
-                  0, TYPE_PRECISION (TREE_TYPE (type)));
-         CHARS (8);
+         CHARS (5);
+
+         dbxout_type (TREE_TYPE (type), 0);
+         fprintf (asmfile, ",0,%d;", TYPE_PRECISION (TREE_TYPE (type)));
+         CHARS (7);
          fprintf (asmfile, "imag:");
          CHARS (5);
-         dbxout_type (TREE_TYPE (type), 0, 0);
-         fprintf (asmfile, ",%d,%d;;",
-                  TYPE_PRECISION (TREE_TYPE (type)),
+         dbxout_type (TREE_TYPE (type), 0);
+         fprintf (asmfile, ",%d,%d;;", TYPE_PRECISION (TREE_TYPE (type)),
                   TYPE_PRECISION (TREE_TYPE (type)));
-         CHARS (9);
+         CHARS (10);
        }
       break;
 
@@ -1297,17 +1583,22 @@ dbxout_type (type, full, show_arg_types)
        {
          have_used_extensions = 1;
          fputs ("@s", asmfile);
-         fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                  BITS_PER_UNIT * int_size_in_bytes (type));
-         fputc (';', asmfile);
+         CHARS (2);
+         print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
+         putc (';', asmfile);
+         CHARS (1);
+
          /* Check if a bitstring type, which in Chill is
             different from a [power]set.  */
          if (TYPE_STRING_FLAG (type))
-           fprintf (asmfile, "@S;");
+           {
+             fprintf (asmfile, "@S;");
+             CHARS (3);
+           }
        }
       putc ('S', asmfile);
       CHARS (1);
-      dbxout_type (TYPE_DOMAIN (type), 0, 0);
+      dbxout_type (TYPE_DOMAIN (type), 0);
       break;
 
     case ARRAY_TYPE:
@@ -1316,15 +1607,14 @@ dbxout_type (type, full, show_arg_types)
        {
          have_used_extensions = 1;
          fputs ("@s", asmfile);
-         fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                  BITS_PER_UNIT * int_size_in_bytes (type));
-         fputc (';', asmfile);
-         fprintf (asmfile, "@S;");
-         putc ('S', asmfile);
-         CHARS (1);
-         dbxout_type (TYPE_DOMAIN (type), 0, 0);
+         CHARS (2);
+         print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
+         fprintf (asmfile, ";@S;S");
+         CHARS (5);
+         dbxout_type (TYPE_DOMAIN (type), 0);
          break;
        }
+
       /* Output "a" followed by a range type definition
         for the index type of the array
         followed by a reference to the target-type.
@@ -1335,21 +1625,25 @@ dbxout_type (type, full, show_arg_types)
        {
          have_used_extensions = 1;
          fprintf (asmfile, "@S;");
+         CHARS (3);
        }
       tem = TYPE_DOMAIN (type);
       if (tem == NULL)
        {
          fprintf (asmfile, "ar");
+         CHARS (2);
          dbxout_type_index (integer_type_node);
          fprintf (asmfile, ";0;-1;");
+         CHARS (6);
        }
       else
        {
          fprintf (asmfile, "a");
+         CHARS (1);
          dbxout_range_type (tem);
        }
-      CHARS (14);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case RECORD_TYPE:
@@ -1371,7 +1665,7 @@ dbxout_type (type, full, show_arg_types)
             && !full)
            || !COMPLETE_TYPE_P (type)
            /* No way in DBX fmt to describe a variable size.  */
-           || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+           || ! host_integerp (TYPE_SIZE (type), 1))
          {
            /* If the type is just a cross reference, output one
               and mark the type as partially described.
@@ -1381,7 +1675,7 @@ dbxout_type (type, full, show_arg_types)
               another type's definition; instead, output an xref
               and let the definition come when the name is defined.  */
            fputs ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu", asmfile);
-           CHARS (3);
+           CHARS (2);
 #if 0 /* This assertion is legitimately false in C++.  */
            /* We shouldn't be outputting a reference to a type before its
               definition unless the type has a tag name.
@@ -1392,16 +1686,21 @@ dbxout_type (type, full, show_arg_types)
            if (TYPE_NAME (type) != 0)
              dbxout_type_name (type);
            else
-             fprintf (asmfile, "$$%d", anonymous_type_number++);
+             {
+               fprintf (asmfile, "$$%d", anonymous_type_number++);
+               CHARS (5);
+             }
+
            fprintf (asmfile, ":");
+           CHARS (1);
            typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
            break;
          }
 
        /* Identify record or union, and print its size.  */
-       fputc (((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u'), asmfile);
-       fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                int_size_in_bytes (type));
+       putc (((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u'), asmfile);
+       CHARS (1);
+       print_wide_int (int_size_in_bytes (type));
 
        if (use_gnu_debug_info_extensions)
          {
@@ -1414,20 +1713,32 @@ dbxout_type (type, full, show_arg_types)
          }
        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);
-               fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                        (tree_low_cst (BINFO_OFFSET (child), 0)
-                         * BITS_PER_UNIT));
-               fputc (',', asmfile);
-               CHARS (15);
-               dbxout_type (BINFO_TYPE (child), 0, 0);
+               putc (access == access_public_node ? '2' : '0', asmfile);
+               CHARS (2);
+               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.  */
+                 print_wide_int (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
+                                 * BITS_PER_UNIT);
+               else
+                 print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
+                                 * BITS_PER_UNIT);
+               putc (',', asmfile);
+               CHARS (1);
+               dbxout_type (BINFO_TYPE (child), 0);
                putc (';', asmfile);
+               CHARS (1);
              }
            else
              {
@@ -1435,24 +1746,23 @@ dbxout_type (type, full, show_arg_types)
                   which have the same names at the types they hold.  */
                dbxout_type_name (BINFO_TYPE (child));
                putc (':', asmfile);
-               dbxout_type (BINFO_TYPE (child), full, 0);
-               fputc (',', asmfile);
-               fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                        tree_low_cst (BINFO_OFFSET (child), 0)
-                        * BITS_PER_UNIT);
-               fputc (',', asmfile);
-               fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                        (tree_low_cst (DECL_SIZE (TYPE_NAME
-                                                 (BINFO_TYPE (child))), 0)
-                         * BITS_PER_UNIT));
-               fputc (';', asmfile);
-               CHARS (20);
+               CHARS (1);
+               dbxout_type (BINFO_TYPE (child), full);
+               putc (',', asmfile);
+               CHARS (1);
+               print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
+                               * BITS_PER_UNIT);
+               putc (',', asmfile);
+               CHARS (1);
+               print_wide_int (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)),
+                                             0)
+                               * BITS_PER_UNIT);
+               putc (';', asmfile);
+               CHARS (1);
              }
          }
       }
 
-      CHARS (11);
-
       /* Write out the field declarations.  */
       dbxout_type_fields (type);
       if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
@@ -1462,6 +1772,7 @@ dbxout_type (type, full, show_arg_types)
        }
 
       putc (';', asmfile);
+      CHARS (1);
 
       if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE
          /* Avoid the ~ if we don't really need it--it confuses dbx.  */
@@ -1471,6 +1782,7 @@ dbxout_type (type, full, show_arg_types)
 
          /* Tell GDB+ that it may keep reading.  */
          putc ('~', asmfile);
+         CHARS (1);
 
          /* We need to write out info about what field this class
             uses as its "main" vtable pointer field, because if this
@@ -1479,10 +1791,12 @@ dbxout_type (type, full, show_arg_types)
          if (TYPE_VFIELD (type))
            {
              putc ('%', asmfile);
-             dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0, 0);
+             CHARS (1);
+             dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0);
            }
+
          putc (';', asmfile);
-         CHARS (3);
+         CHARS (1);
        }
       break;
 
@@ -1497,48 +1811,48 @@ dbxout_type (type, full, show_arg_types)
          || !COMPLETE_TYPE_P (type))
        {
          fprintf (asmfile, "xe");
-         CHARS (3);
+         CHARS (2);
          dbxout_type_name (type);
          typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
-         fprintf (asmfile, ":");
+         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))
-       fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
+       {
+         fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
+         CHARS (5);
+       }
+
       putc ('e', asmfile);
       CHARS (1);
       for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
        {
          fprintf (asmfile, "%s:", IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
+         CHARS (IDENTIFIER_LENGTH (TREE_PURPOSE (tem)) + 1);
          if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0)
-           fprintf (asmfile, HOST_WIDE_INT_PRINT_UNSIGNED,
-                    TREE_INT_CST_LOW (TREE_VALUE (tem)));
+           print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem)));
          else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1
                   && (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)
-           fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
-                    TREE_INT_CST_LOW (TREE_VALUE (tem)));
+           print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem)));
          else
            print_int_cst_octal (TREE_VALUE (tem));
-         fprintf (asmfile, ",");
-         CHARS (20 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem)));
+
+         putc (',', asmfile);
+         CHARS (1);
          if (TREE_CHAIN (tem) != 0)
-           {
-             CONTIN;
-           }
+           CONTIN;
        }
+
       putc (';', asmfile);
       CHARS (1);
-#endif
       break;
 
     case POINTER_TYPE:
       putc ('*', asmfile);
       CHARS (1);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case METHOD_TYPE:
@@ -1547,34 +1861,19 @@ dbxout_type (type, full, show_arg_types)
          have_used_extensions = 1;
          putc ('#', asmfile);
          CHARS (1);
-         if (flag_minimal_debug && !show_arg_types)
-           {
-             /* Normally, just output the return type.
-                The argument types are encoded in the method name.  */
-             putc ('#', asmfile);
-             CHARS (1);
-             dbxout_type (TREE_TYPE (type), 0, 0);
-             putc (';', asmfile);
-             CHARS (1);
-           }
-         else
-           {
-             /* When outputting destructors, we need to write
-                the argument types out longhand.  */
-             dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0);
-             putc (',', asmfile);
-             CHARS (1);
-             dbxout_type (TREE_TYPE (type), 0, 0);
-             dbxout_args (TYPE_ARG_TYPES (type));
-             putc (';', asmfile);
-             CHARS (1);
-           }
+
+         /* Write the argument types out longhand.  */
+         dbxout_type (TYPE_METHOD_BASETYPE (type), 0);
+         putc (',', asmfile);
+         CHARS (1);
+         dbxout_type (TREE_TYPE (type), 0);
+         dbxout_args (TYPE_ARG_TYPES (type));
+         putc (';', asmfile);
+         CHARS (1);
        }
       else
-       {
-         /* Treat it as a function type.  */
-         dbxout_type (TREE_TYPE (type), 0, 0);
-       }
+       /* Treat it as a function type.  */
+       dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case OFFSET_TYPE:
@@ -1583,17 +1882,14 @@ dbxout_type (type, full, show_arg_types)
          have_used_extensions = 1;
          putc ('@', asmfile);
          CHARS (1);
-         dbxout_type (TYPE_OFFSET_BASETYPE (type), 0, 0);
+         dbxout_type (TYPE_OFFSET_BASETYPE (type), 0);
          putc (',', asmfile);
          CHARS (1);
-         dbxout_type (TREE_TYPE (type), 0, 0);
+         dbxout_type (TREE_TYPE (type), 0);
        }
       else
-       {
-         /* Should print as an int, because it is really
-            just an offset.  */
-         dbxout_type (integer_type_node, 0, 0);
-       }
+       /* Should print as an int, because it is really just an offset.  */
+       dbxout_type (integer_type_node, 0);
       break;
 
     case REFERENCE_TYPE:
@@ -1601,13 +1897,13 @@ dbxout_type (type, full, show_arg_types)
        have_used_extensions = 1;
       putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile);
       CHARS (1);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case FUNCTION_TYPE:
       putc ('f', asmfile);
       CHARS (1);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     default:
@@ -1615,12 +1911,44 @@ dbxout_type (type, full, show_arg_types)
     }
 }
 
+/* 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);
@@ -1640,6 +1968,7 @@ print_int_cst_octal (c)
     high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
 
   fprintf (asmfile, "0");
+  CHARS (1);
 
   if (excess == 3)
     {
@@ -1658,19 +1987,38 @@ print_int_cst_octal (c)
                 - 1);
 
       fprintf (asmfile, "%o%01o", (int) beg, (int) middle);
+      CHARS (2);
       print_octal (end, HOST_BITS_PER_WIDE_INT / 3);
     }
 }
 
 static void
-print_octal (value, digits)
-     unsigned HOST_WIDE_INT value;
-     int digits;
+print_octal (unsigned HOST_WIDE_INT value, int digits)
 {
   int i;
 
   for (i = digits - 1; i >= 0; i--)
     fprintf (asmfile, "%01o", (int) ((value >> (3 * i)) & 7));
+
+  CHARS (digits);
+}
+
+/* Output C in decimal while adjusting the number of digits written.  */
+
+static void
+print_wide_int (HOST_WIDE_INT c)
+{
+  int digs = 0;
+
+  fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, c);
+
+  if (c < 0)
+    digs++, c = -c;
+
+  while (c > 0)
+    c /= 10; digs++;
+
+  CHARS (digs);
 }
 
 /* Output the name of type TYPE, with no punctuation.
@@ -1678,8 +2026,7 @@ print_octal (value, digits)
    or by struct, enum and union tags.  */
 
 static void
-dbxout_type_name (type)
-     register tree type;
+dbxout_type_name (tree type)
 {
   tree t;
   if (TYPE_NAME (type) == 0)
@@ -1698,6 +2045,34 @@ dbxout_type_name (type)
   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.
@@ -1706,14 +2081,15 @@ dbxout_type_name (type)
    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;
@@ -1723,7 +2099,64 @@ dbxout_symbol (decl, local)
 
   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);
 
@@ -1741,7 +2174,7 @@ dbxout_symbol (decl, local)
 
     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.  */
@@ -1762,9 +2195,9 @@ dbxout_symbol (decl, local)
       current_sym_addr = XEXP (DECL_RTL (decl), 0);
 
       if (TREE_TYPE (type))
-       dbxout_type (TREE_TYPE (type), 0, 0);
+       dbxout_type (TREE_TYPE (type), 0);
       else
-       dbxout_type (void_type_node, 0, 0);
+       dbxout_type (void_type_node, 0);
 
       /* For a nested function, when that function is compiled,
         mention the containing function name
@@ -1778,22 +2211,10 @@ dbxout_symbol (decl, local)
       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;
@@ -1818,7 +2239,13 @@ dbxout_symbol (decl, local)
                && !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.  */
+               && host_integerp (TYPE_SIZE (type), 1))
              {
                tree name = TYPE_NAME (type);
                if (TREE_CODE (name) == TYPE_DECL)
@@ -1831,13 +2258,21 @@ dbxout_symbol (decl, local)
 
                fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP,
                         IDENTIFIER_POINTER (name));
-               dbxout_type (type, 1, 0);
+               dbxout_type (type, 1);
                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
@@ -1846,7 +2281,7 @@ dbxout_symbol (decl, local)
                && 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)
                  {
@@ -1862,13 +2297,13 @@ dbxout_symbol (decl, local)
            putc ('t', asmfile);
            current_sym_code = DBX_TYPE_DECL_STABS_CODE;
 
-           dbxout_type (type, 1, 0);
+           dbxout_type (type, 1);
            dbxout_finish_symbol (decl);
            did_output = 1;
          }
 
-       /* Don't output a tag if this is an incomplete type (TYPE_SIZE is
-          zero).  This prevents the sun4 Sun OS 4.x dbx from crashing.  */ 
+       /* Don't output a tag if this is an incomplete type.  This prevents
+          the sun4 Sun OS 4.x dbx from crashing.  */
 
        if (tag_needed && TYPE_NAME (type) != 0
            && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE
@@ -1892,7 +2327,7 @@ dbxout_symbol (decl, local)
 
            fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP,
                     IDENTIFIER_POINTER (name));
-           dbxout_type (type, 1, 0);
+           dbxout_type (type, 1);
            dbxout_finish_symbol (NULL_TREE);
            did_output = 1;
          }
@@ -1910,7 +2345,7 @@ dbxout_symbol (decl, local)
            /* Some debuggers fail when given NULL names, so give this a
               harmless name of ` '.  */
            fprintf (asmfile, "%s\" :T", ASM_STABS_OP);
-           dbxout_type (type, 1, 0);
+           dbxout_type (type, 1);
            dbxout_finish_symbol (NULL_TREE);
          }
 
@@ -1927,8 +2362,8 @@ dbxout_symbol (decl, local)
     case RESULT_DECL:
       /* Named return value, treat like a VAR_DECL.  */
     case VAR_DECL:
-      if (DECL_RTL (decl) == 0)
-       return 0;
+      if (! DECL_RTL_SET_P (decl))
+       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))
@@ -1952,14 +2387,10 @@ dbxout_symbol (decl, local)
                  || 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)
@@ -1979,10 +2410,11 @@ dbxout_symbol (decl, local)
 
       result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
       break;
-      
+
     default:
       break;
     }
+  DBXOUT_DECR_NESTING;
   return result;
 }
 \f
@@ -1993,43 +2425,37 @@ dbxout_symbol (decl, local)
    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.  */
-  if (GET_CODE (home) == REG)
-    {
-      regno = REGNO (home);
-      if (regno >= FIRST_PSEUDO_REGISTER)
-       return 0;
-    }
-  else if (GET_CODE (home) == SUBREG)
+  if (GET_CODE (home) == SUBREG)
     {
       rtx value = home;
-      int offset = 0;
+
       while (GET_CODE (value) == SUBREG)
-       {
-         offset += SUBREG_WORD (value);
-         value = SUBREG_REG (value);
-       }
+       value = SUBREG_REG (value);
       if (GET_CODE (value) == REG)
        {
-         regno = REGNO (value);
-         if (regno >= FIRST_PSEUDO_REGISTER)
+         if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
            return 0;
-         regno += offset;
        }
-      alter_subreg (home);
+      home = alter_subreg (&home);
+    }
+  if (GET_CODE (home) == REG)
+    {
+      regno = REGNO (home);
+      if (regno >= FIRST_PSEUDO_REGISTER)
+       return 0;
     }
 
   /* The kind-of-variable letter depends on where
@@ -2064,7 +2490,7 @@ dbxout_symbol_location (decl, type, suffix, home)
             we rely on the fact that error_mark_node initializers always
             end up in bss for C++ and never end up in bss for C.  */
          if (DECL_INITIAL (decl) == 0
-             || (!strcmp (lang_identify (), "cplusplus")
+             || (!strcmp (lang_hooks.name, "GNU C++")
                  && DECL_INITIAL (decl) == error_mark_node))
            current_sym_code = N_LCSYM;
          else if (DECL_IN_TEXT_SECTION (decl))
@@ -2073,6 +2499,21 @@ dbxout_symbol_location (decl, type, suffix, home)
            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 ();
@@ -2108,6 +2549,8 @@ dbxout_symbol_location (decl, type, suffix, home)
        {
          letter = 'r';
          current_sym_code = N_RSYM;
+         if (REGNO (XEXP (home, 0)) >= FIRST_PSEUDO_REGISTER)
+           return 0;
          current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0)));
        }
       else
@@ -2161,7 +2604,15 @@ dbxout_symbol_location (decl, type, suffix, home)
     }
   else if (GET_CODE (home) == CONCAT)
     {
-      tree subtype = TREE_TYPE (type);
+      tree subtype;
+
+      /* If TYPE is not a COMPLEX_TYPE (it might be a RECORD_TYPE,
+        for example), then there is no easy way to figure out
+        what SUBTYPE should be.  So, we give up.  */
+      if (TREE_CODE (type) != COMPLEX_TYPE)
+       return 0;
+
+      subtype = TREE_TYPE (type);
 
       /* If the variable's storage is in two parts,
         output each as a separate stab with a modified name.  */
@@ -2196,7 +2647,7 @@ dbxout_symbol_location (decl, type, suffix, home)
 #endif
 
   dbxout_symbol_name (decl, suffix, letter);
-  dbxout_type (type, 0, 0);
+  dbxout_type (type, 0);
   dbxout_finish_symbol (decl);
 
 #ifdef DBX_STATIC_BLOCK_END
@@ -2209,10 +2660,7 @@ dbxout_symbol_location (decl, type, suffix, home)
    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;
 
@@ -2232,12 +2680,12 @@ dbxout_symbol_name (decl, suffix, letter)
   fprintf (asmfile, "%s\"%s%s:", ASM_STABS_OP, name,
           (suffix ? suffix : ""));
 
-  if (letter) putc (letter, asmfile);
+  if (letter)
+    putc (letter, asmfile);
 }
 
 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);
@@ -2247,8 +2695,7 @@ dbxout_prepare_symbol (decl)
 }
 
 static void
-dbxout_finish_symbol (sym)
-     tree sym;
+dbxout_finish_symbol (tree sym)
 {
 #ifdef DBX_FINISH_SYMBOL
   DBX_FINISH_SYMBOL (sym);
@@ -2266,12 +2713,11 @@ dbxout_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)
@@ -2295,9 +2741,12 @@ dbxout_syms (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)
       {
@@ -2350,8 +2799,8 @@ dbxout_parms (parms)
              }
 
            /* It is quite tempting to use:
-              
-                  dbxout_type (TREE_TYPE (parms), 0, 0);
+
+                  dbxout_type (TREE_TYPE (parms), 0);
 
               as the next statement, rather than using DECL_ARG_TYPE(), so
               that gcc reports the actual type of the parameter, rather
@@ -2362,8 +2811,8 @@ dbxout_parms (parms)
               passing a float to an unprototyped function, gcc will store a
               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 erropneous value.  */
-           dbxout_type (DECL_ARG_TYPE (parms), 0, 0);
+              produce an erroneous value.  */
+           dbxout_type (DECL_ARG_TYPE (parms), 0);
            current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
            dbxout_finish_symbol (parms);
          }
@@ -2414,7 +2863,7 @@ dbxout_parms (parms)
                         regparm_letter);
              }
 
-           dbxout_type (parm_type, 0, 0);
+           dbxout_type (parm_type, 0);
            dbxout_finish_symbol (parms);
          }
        else if (GET_CODE (DECL_RTL (parms)) == MEM
@@ -2454,7 +2903,8 @@ dbxout_parms (parms)
            FORCE_TEXT;
            if (DECL_NAME (parms))
              {
-               current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
+               current_sym_nchars
+                 = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
 
                fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
                         IDENTIFIER_POINTER (DECL_NAME (parms)),
@@ -2467,7 +2917,7 @@ dbxout_parms (parms)
                         regparm_letter);
              }
 
-           dbxout_type (TREE_TYPE (parms), 0, 0);
+           dbxout_type (TREE_TYPE (parms), 0);
            dbxout_finish_symbol (parms);
          }
        else if (GET_CODE (DECL_RTL (parms)) == MEM
@@ -2477,19 +2927,24 @@ dbxout_parms (parms)
               living on the stack.  DECL_RTL looks like
               (MEM (MEM (PLUS (REG ...) (CONST_INT ...)))) or it
               could look like (MEM (MEM (REG))).  */
-           const char *decl_name = (DECL_NAME (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);
-           dbxout_type (TREE_TYPE (parms), 0, 0);
+
+           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);
          }
        else if (GET_CODE (DECL_RTL (parms)) == MEM
@@ -2520,7 +2975,7 @@ dbxout_parms (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)));
              }
@@ -2545,10 +3000,11 @@ dbxout_parms (parms)
            current_sym_value
              = DEBUGGER_ARG_OFFSET (current_sym_value,
                                     XEXP (DECL_RTL (parms), 0));
-           dbxout_type (TREE_TYPE (parms), 0, 0);
+           dbxout_type (TREE_TYPE (parms), 0);
            dbxout_finish_symbol (parms);
          }
       }
+  DBXOUT_DECR_NESTING;
 }
 
 /* Output definitions for the places where parms live during the function,
@@ -2563,9 +3019,10 @@ dbxout_parms (parms)
    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))
       {
@@ -2586,42 +3043,24 @@ dbxout_reg_parms (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 */
 
-void
-dbxout_args (args)
-     tree args;
+static void
+dbxout_args (tree args)
 {
   while (args)
     {
       putc (',', asmfile);
-      dbxout_type (TREE_VALUE (args), 0, 0);
+      dbxout_type (TREE_VALUE (args), 0);
       CHARS (1);
       args = TREE_CHAIN (args);
     }
 }
 \f
-/* Given a chain of ..._TYPE nodes,
-   find those which have typedef names and output those names.
-   This is to ensure those types get output.  */
-
-void
-dbxout_types (types)
-     register tree types;
-{
-  while (types)
-    {
-      if (TYPE_NAME (types)
-         && TREE_CODE (TYPE_NAME (types)) == TYPE_DECL
-         && ! TREE_ASM_WRITTEN (TYPE_NAME (types)))
-       dbxout_symbol (TYPE_NAME (types), 1);
-      types = TREE_CHAIN (types);
-    }
-}
-\f
 /* Output everything about a symbol block (a BLOCK node
    that represents a scope level),
    including recursive output of contained blocks.
@@ -2640,15 +3079,12 @@ dbxout_types (types)
    We handle them all in sequence.  */
 
 static void
-dbxout_block (block, depth, args)
-     register 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
@@ -2662,17 +3098,13 @@ dbxout_block (block, depth, args)
        {
          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. */
+            If nothing is output, we don't need the N_LBRAC, either.  */
          did_output = 0;
          if (debug_info_level != DINFO_LEVEL_TERSE || depth == 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
@@ -2690,14 +3122,10 @@ dbxout_block (block, depth, args)
                  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);
                    }
                }
@@ -2708,22 +3136,13 @@ dbxout_block (block, depth, args)
              fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_LBRAC);
              assemble_name (asmfile, buf);
 #if DBX_BLOCKS_FUNCTION_RELATIVE
-             fputc ('-', asmfile);
+             putc ('-', asmfile);
              assemble_name (asmfile, begin_label);
 #endif
              fprintf (asmfile, "\n");
 #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);
 
@@ -2738,7 +3157,7 @@ dbxout_block (block, depth, args)
              fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_RBRAC);
              assemble_name (asmfile, buf);
 #if DBX_BLOCKS_FUNCTION_RELATIVE
-             fputc ('-', asmfile);
+             putc ('-', asmfile);
              assemble_name (asmfile, begin_label);
 #endif
              fprintf (asmfile, "\n");
@@ -2753,51 +3172,29 @@ dbxout_block (block, depth, args)
    Usually this follows the function's code,
    but on some systems, it comes before.  */
 
+#if defined (DBX_DEBUGGING_INFO)
 static void
-dbxout_really_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 */
 
-/* Called at beginning of output of function definition.  */
-
-void
-dbxout_begin_function (decl)
-     tree decl ATTRIBUTE_UNUSED;
-{
-#ifdef DBX_FUNCTION_FIRST
-  dbxout_really_begin_function (decl);
-#endif
-}
-
-/* Output dbx data for a function definition.
-   This includes a definition of the function name itself (a symbol),
-   definitions of the parameters (locating them in the parameter list)
-   and then output the block that makes up the function's body
-   (including all the auto variables of the function).  */
-
-void
-dbxout_function (decl)
-     tree decl;
-{
-#ifndef DBX_FUNCTION_FIRST
-  dbxout_really_begin_function (decl);
-#endif
-  dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
-#ifdef DBX_OUTPUT_FUNCTION_END
-  DBX_OUTPUT_FUNCTION_END (asmfile, decl);
-#endif
-#if defined(ASM_OUTPUT_SECTION_NAME)
-  if (use_gnu_debug_info_extensions
-#if defined(NO_DBX_FUNCTION_END)
-      && ! NO_DBX_FUNCTION_END
-#endif
-      )
-    dbxout_function_end ();
-#endif
-}
 #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+#include "gt-dbxout.h"