OSDN Git Service

* expr.c (build_java_arraystore_check): Fix formatting.
[pf3gnuchains/gcc-fork.git] / gcc / dbxout.c
index 6922799..2db1f3a 100644 (file)
@@ -1,21 +1,23 @@
 /* Output dbx-format symbol table information from GNU compiler.
-   Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001 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, 675 Mass Ave, Cambridge, MA 02139, 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.
@@ -66,34 +68,35 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
    For more on data type definitions, see `dbxout_type'.  */
 
-/* Include these first, because they may define MIN and MAX.  */
-#include <stdio.h>
-#include <errno.h>
-
 #include "config.h"
+#include "system.h"
+
 #include "tree.h"
 #include "rtl.h"
 #include "flags.h"
 #include "regs.h"
 #include "insn-config.h"
 #include "reload.h"
-#include "defaults.h"
 #include "output.h" /* ASM_OUTPUT_SOURCE_LINE may refer to sdb functions.  */
-
-#ifndef errno
-extern int errno;
-#endif
+#include "dbxout.h"
+#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
 
 #ifndef ASM_STABS_OP
-#define ASM_STABS_OP ".stabs"
+#define ASM_STABS_OP "\t.stabs\t"
 #endif
 
 #ifndef ASM_STABN_OP
-#define ASM_STABN_OP ".stabn"
+#define ASM_STABN_OP "\t.stabn\t"
 #endif
 
 #ifndef DBX_TYPE_DECL_STABS_CODE
@@ -112,6 +115,11 @@ extern int errno;
 #define DBX_REGPARM_STABS_LETTER 'P'
 #endif
 
+/* This is used for parameters passed by invisible reference in a register.  */
+#ifndef GDB_INV_REF_REGPARM_STABS_LETTER
+#define GDB_INV_REF_REGPARM_STABS_LETTER 'a'
+#endif
+
 #ifndef DBX_MEMPARM_STABS_LETTER
 #define DBX_MEMPARM_STABS_LETTER 'p'
 #endif
@@ -120,10 +128,17 @@ extern int errno;
 #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.  */
+/* 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
+
+/* Typical USG systems don't have stab.h, and they also have
+   no use for DBX-format debugging info.  */
 
-static int flag_minimal_debug = 1;
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
 
 /* Nonzero if we have actually used any of the GDB extensions
    to the debugging format.  The idea is that we use them for the
@@ -132,12 +147,12 @@ static int flag_minimal_debug = 1;
 
 static int have_used_extensions = 0;
 
-char *getpwd ();
-
-/* Typical USG systems don't have stab.h, and they also have
-   no use for DBX-format debugging info.  */
+/* Number for the next N_SOL filename stabs label.  The number 0 is reserved
+   for the N_SO filename stabs label.  */
 
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
+static int source_label_number = 1;
+#endif
 
 #ifdef DEBUG_SYMS_TEXT
 #define FORCE_TEXT text_section ();
@@ -145,22 +160,9 @@ char *getpwd ();
 #define FORCE_TEXT
 #endif
 
-#if defined (USG) || defined (NO_STAB_H)
-#include "gstab.h"  /* If doing DBX on sysV, use our own stab.h.  */
-#else
-#include <stab.h>  /* On BSD, use the system's stab.h.  */
-
-/* This is a GNU extension we need to reference in this file.  */
-#ifndef N_CATCH
-#define N_CATCH 0x54
-#endif
-#endif /* not USG */
+#include "gstab.h"
 
-#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.  */
 
@@ -186,23 +188,36 @@ static FILE *asmfile;
 
 /* Last source file name mentioned in a NOTE insn.  */
 
-static char *lastfile;
+static const char *lastfile;
 
 /* Current working directory.  */
 
-static char *cwd;
+static const char *cwd;
 
 enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
 
-/* Vector recording the status of describing C data types.
+/* Structure recording information about a C data type.
+   The status element says whether we have yet output
+   the definition of the type.  TYPE_XREF says we have
+   output it as a cross-reference only.
+   The file_number and type_number elements are used if DBX_USE_BINCL
+   is defined.  */
+
+struct typeinfo
+{
+  enum typestatus status;
+#ifdef DBX_USE_BINCL
+  int file_number;
+  int type_number;
+#endif
+};
+
+/* Vector recording information about C data types.
    When we first notice a data type (a tree node),
    we assign it a number using next_type_number.
-   That is its index in this vector.
-   The vector element says whether we have yet output
-   the definition of the type.  TYPE_XREF says we have
-   output it as a cross-reference only.  */
+   That is its index in this vector.  */
 
-enum typestatus *typevec;
+struct typeinfo *typevec;
 
 /* Number of elements of space allocated in `typevec'.  */
 
@@ -214,15 +229,28 @@ static int typevec_len;
 
 static int next_type_number;
 
-/* In dbx output, we must assign symbol-blocks id numbers
-   in the order in which their beginnings are encountered.
-   We output debugging info that refers to the beginning and
-   end of the ranges of code in each block
-   with assembler labels LBBn and LBEn, where n is the block number.
-   The labels are generated in final, which assigns numbers to the
-   blocks in the same way.  */
+#ifdef DBX_USE_BINCL
+
+/* 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 *next;
+  int file_number;
+  int next_type_number;
+};
+
+/* This is the top of the stack.  */
+
+static struct dbx_file *current_file;
 
-static int next_block_number;
+/* This is the next file number to use.  */
+
+static int next_file_number;
+
+#endif /* DBX_USE_BINCL */
 
 /* These variables are for dbxout_symbol to communicate to
    dbxout_finish_symbol.
@@ -258,143 +286,138 @@ static int current_sym_nchars;
 #define CONTIN  \
   do {if (current_sym_nchars > DBX_CONTIN_LENGTH) dbxout_continue ();} while (0)
 #else
-#define CONTIN
+#define CONTIN do { } while (0)
 #endif
 
-void dbxout_types ();
-void dbxout_args ();
-void dbxout_symbol ();
-static void dbxout_type_name ();
-static void dbxout_type ();
-static void dbxout_typedefs ();
-static void dbxout_symbol_name ();
-static void dbxout_symbol_location ();
-static void dbxout_prepare_symbol ();
-static void dbxout_finish_symbol ();
-static void dbxout_continue ();
-static void print_int_cst_octal ();
-static void print_octal ();
+static void dbxout_init                        PARAMS ((const char *));
+static void dbxout_finish              PARAMS ((const char *));
+static void dbxout_start_source_file   PARAMS ((unsigned, const char *));
+static void dbxout_end_source_file     PARAMS ((unsigned));
+static void dbxout_typedefs            PARAMS ((tree));
+static void dbxout_type_index          PARAMS ((tree));
+#if DBX_CONTIN_LENGTH > 0
+static void dbxout_continue            PARAMS ((void));
+#endif
+static void dbxout_args                        PARAMS ((tree));
+static void dbxout_type_fields         PARAMS ((tree));
+static void dbxout_type_method_1       PARAMS ((tree, const char *));
+static void dbxout_type_methods                PARAMS ((tree));
+static void dbxout_range_type          PARAMS ((tree));
+static void dbxout_type                        PARAMS ((tree, int));
+static void print_int_cst_octal                PARAMS ((tree));
+static void print_octal                        PARAMS ((unsigned HOST_WIDE_INT, int));
+static void print_wide_int             PARAMS ((HOST_WIDE_INT));
+static void dbxout_type_name           PARAMS ((tree));
+static int dbxout_symbol_location      PARAMS ((tree, tree, const char *, rtx));
+static void dbxout_symbol_name         PARAMS ((tree, const char *, int));
+static void dbxout_prepare_symbol      PARAMS ((tree));
+static void dbxout_finish_symbol       PARAMS ((tree));
+static void dbxout_block               PARAMS ((tree, int, tree));
+static void dbxout_global_decl         PARAMS ((tree));
 \f
-#if 0 /* Not clear we will actually need this.  */
-
-/* Return the absolutized filename for the given relative
-   filename.  Note that if that filename is already absolute, it may
-   still be returned in a modified form because this routine also
-   eliminates redundant slashes and single dots and eliminates double
-   dots to get a shortest possible filename from the given input
-   filename.  The absolutization of relative filenames is made by
-   assuming that the given filename is to be taken as relative to
-   the first argument (cwd) or to the current directory if cwd is
-   NULL.  */
-
-static char *
-abspath (rel_filename)
-     char *rel_filename;
+/* The debug hooks structure.  */
+#if defined (DBX_DEBUGGING_INFO)
+
+static void dbxout_source_line         PARAMS ((unsigned int, const char *));
+static void dbxout_source_file         PARAMS ((FILE *, const char *));
+static void dbxout_function_end                PARAMS ((void));
+static void dbxout_begin_function      PARAMS ((tree));
+static void dbxout_begin_block         PARAMS ((unsigned, unsigned));
+static void dbxout_end_block           PARAMS ((unsigned, unsigned));
+static void dbxout_function_decl       PARAMS ((tree));
+
+struct gcc_debug_hooks dbx_debug_hooks =
 {
-  /* Setup the current working directory as needed.  */
-  char *abs_buffer
-    = (char *) alloca (strlen (cwd) + strlen (rel_filename) + 1);
-  char *endp = abs_buffer;
-  char *outp, *inp;
-  char *value;
-
-  /* Copy the filename (possibly preceded by the current working
-     directory name) into the absolutization buffer.  */
-
-  {
-    char *src_p;
-
-    if (rel_filename[0] != '/')
-      {
-        src_p = cwd;
-        while (*endp++ = *src_p++)
-          continue;
-        *(endp-1) = '/';                       /* overwrite null */
-      }
-    src_p = rel_filename;
-    while (*endp++ = *src_p++)
-      continue;
-    if (endp[-1] == '/')
-      *endp = '\0';
-
-  /* Now make a copy of abs_buffer into abs_buffer, shortening the
-     filename (by taking out slashes and dots) as we go.  */
-
-  outp = inp = abs_buffer;
-  *outp++ = *inp++;            /* copy first slash */
-  for (;;)
-    {
-      if (!inp[0])
-        break;
-      else if (inp[0] == '/' && outp[-1] == '/')
-        {
-          inp++;
-          continue;
-        }
-      else if (inp[0] == '.' && outp[-1] == '/')
-        {
-          if (!inp[1])
-                  break;
-          else if (inp[1] == '/')
-            {
-                    inp += 2;
-                    continue;
-            }
-          else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
-            {
-                    inp += (inp[2] == '/') ? 3 : 2;
-                    outp -= 2;
-                    while (outp >= abs_buffer && *outp != '/')
-               outp--;
-                    if (outp < abs_buffer)
-                {
-                  /* Catch cases like /.. where we try to backup to a
-                     point above the absolute root of the logical file
-                     system.  */
-
-                 fprintf (stderr, "%s: invalid file name: %s\n",
-                          pname, rel_filename);
-                 exit (1);
-               }
-                    *++outp = '\0';
-                    continue;
-            }
-        }
-      *outp++ = *inp++;
-    }
-
-  /* On exit, make sure that there is a trailing null, and make sure that
-     the last character of the returned string is *not* a slash.  */
-
-  *outp = '\0';
-  if (outp[-1] == '/')
-    *--outp  = '\0';
-
-  /* Make a copy (in the heap) of the stuff left in the absolutization
-     buffer and return a pointer to the copy.  */
-
-  value = (char *) oballoc (strlen (abs_buffer) + 1);
-  strcpy (value, abs_buffer);
-  return value;
-}
-#endif /* 0 */
+  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,           /* end_prologue */
+  debug_nothing_void,          /* 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 */
+};
+#endif /* DBX_DEBUGGING_INFO  */
+
+#if defined (XCOFF_DEBUGGING_INFO)
+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,           /* 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 */
+};
+#endif /* XCOFF_DEBUGGING_INFO  */
 \f
+#if defined (DBX_DEBUGGING_INFO)
+static void
+dbxout_function_end ()
+{
+  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);
+  scope_labelno++;
+
+  /* By convention, GCC will mark the end of a function with an N_FUN
+     symbol and an empty string.  */
+  fprintf (asmfile, "%s\"\",%d,0,0,", ASM_STABS_OP, N_FUN);
+  assemble_name (asmfile, lscope_label_name);
+  putc ('-', asmfile);
+  assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+  fprintf (asmfile, "\n");
+}
+#endif /* 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;
-     char *input_file_name;
-     tree syms;
+static void
+dbxout_init (input_file_name)
+     const char *input_file_name;
 {
   char ltext_label_name[100];
+  tree syms = getdecls ();
 
-  asmfile = asm_file;
+  asmfile = asm_out_file;
 
   typevec_len = 100;
-  typevec = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]);
-  bzero (typevec, typevec_len * sizeof typevec[0]);
+  typevec = (struct typeinfo *) xcalloc (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
@@ -408,19 +431,17 @@ dbxout_init (asm_file, input_file_name, syms)
 #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;
-       }
+       cwd = concat (cwd, FILE_NAME_JOINER, NULL);
       if (cwd)
        {
 #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
          DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asmfile, cwd);
 #else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
-         fprintf (asmfile, "%s ", ASM_STABS_OP);
+         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 */
        }
     }
@@ -433,25 +454,34 @@ dbxout_init (asm_file, input_file_name, syms)
   /* We include outputting `Ltext:' here,
      because that gives you a way to override it.  */
   /* Used to put `Ltext:' before the reference, but that loses on sun 4.  */
-  fprintf (asmfile, "%s ", ASM_STABS_OP);
+  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);
 #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;
 
   next_type_number = 1;
-  next_block_number = 2;
+
+#ifdef DBX_USE_BINCL
+  current_file = (struct dbx_file *) xmalloc (sizeof *current_file);
+  current_file->next = NULL;
+  current_file->file_number = 0;
+  current_file->next_type_number = 1;
+  next_file_number = 1;
+#endif
 
   /* Make sure that types `int' and `char' have numbers 1 and 2.
      Definitions of other integer types will refer to those numbers.
@@ -488,67 +518,189 @@ dbxout_typedefs (syms)
          tree type = TREE_TYPE (syms);
          if (TYPE_NAME (type)
              && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+             && COMPLETE_TYPE_P (type)
              && ! TREE_ASM_WRITTEN (TYPE_NAME (type)))
            dbxout_symbol (TYPE_NAME (type), 0);
        }
     }
 }
 
+/* Change to reading from a new source file.  Generate a N_BINCL stab.  */
+
+static void
+dbxout_start_source_file (line, filename)
+     unsigned int line ATTRIBUTE_UNUSED;
+     const char *filename ATTRIBUTE_UNUSED;
+{
+#ifdef DBX_USE_BINCL
+  struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
+
+  n->next = current_file;
+  n->file_number = next_file_number++;
+  n->next_type_number = 1;
+  current_file = n;
+  fprintf (asmfile, "%s", ASM_STABS_OP);
+  output_quoted_string (asmfile, filename);
+  fprintf (asmfile, ",%d,0,0,0\n", N_BINCL);
+#endif
+}
+
+/* Revert to reading a previous source file.  Generate a N_EINCL stab.  */
+
+static void
+dbxout_end_source_file (line)
+     unsigned int line ATTRIBUTE_UNUSED;
+{
+#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;
+#endif
+}
+
+#if defined (DBX_DEBUGGING_INFO)
 /* Output debugging info to FILE to switch to sourcefile FILENAME.  */
 
-void
+static void
 dbxout_source_file (file, filename)
      FILE *file;
-     char *filename;
+     const char *filename;
 {
-  char ltext_label_name[100];
-
   if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
     {
 #ifdef DBX_OUTPUT_SOURCE_FILENAME
       DBX_OUTPUT_SOURCE_FILENAME (file, filename);
 #else
-      ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
-      fprintf (file, "%s ", ASM_STABS_OP);
+      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);
+      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;
-     char *filename;
-     int lineno;
+static void
+dbxout_source_line (lineno, filename)
+     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);
+  ASM_OUTPUT_SOURCE_LINE (asmfile, lineno);
 #else
-  fprintf (file, "\t%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 (line, n)
+     unsigned int line ATTRIBUTE_UNUSED;
+     unsigned int n;
+{
+  ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBB", n);
+}
+
+/* Describe the end line-number of an internal block within a function.  */
+
+static void
+dbxout_end_block (line, n)
+     unsigned int line ATTRIBUTE_UNUSED;
+     unsigned int n;
+{
+  ASM_OUTPUT_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 (decl)
+     tree decl;
+{
+#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 (decl)
+     tree decl;
+{
+  if (TREE_CODE (decl) == VAR_DECL
+      && ! DECL_EXTERNAL (decl)
+      && DECL_RTL_SET_P (decl))        /* Not necessary?  */
+    dbxout_symbol (decl, 0);
+} 
+
 /* 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. */
+   to do nothing.  */
 
-void
-dbxout_finish (file, filename)
-     FILE *file;
-     char *filename;
+static void
+dbxout_finish (filename)
+     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 */
 }
 
+/* Output the index of a type.  */
+
+static void
+dbxout_type_index (type)
+     tree type;
+{
+#ifndef DBX_USE_BINCL
+  fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
+  CHARS (3);
+#else
+  struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)];
+  fprintf (asmfile, "(%d,%d)", t->file_number, t->type_number);
+  CHARS (9);
+#endif
+}
+
+#if DBX_CONTIN_LENGTH > 0
 /* Continue a symbol-description that gets too big.
    End one symbol table entry with a double-backslash
    and start a new one, eventually producing something like
@@ -564,9 +716,10 @@ dbxout_continue ()
   fprintf (asmfile, "\\\\");
 #endif
   dbxout_finish_symbol (NULL_TREE);
-  fprintf (asmfile, "%s \"", ASM_STABS_OP);
+  fprintf (asmfile, "%s\"", ASM_STABS_OP);
   current_sym_nchars = 0;
 }
+#endif /* DBX_CONTIN_LENGTH > 0 */
 \f
 /* Subroutine of `dbxout_type'.  Output the type fields of TYPE.
    This must be a separate function because anonymous unions require
@@ -577,47 +730,41 @@ dbxout_type_fields (type)
      tree type;
 {
   tree tem;
+
   /* Output the name, type, position (in bits), size (in bits) of each
-     field.  */
+     field that we can support.  */
   for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
     {
-      /* For nameless subunions and subrecords, treat their fields as ours.  */
-      if (DECL_NAME (tem) == NULL_TREE
-         && (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-             || TREE_CODE (TREE_TYPE (tem)) == QUAL_UNION_TYPE
-             || TREE_CODE (TREE_TYPE (tem)) == RECORD_TYPE))
-       dbxout_type_fields (TREE_TYPE (tem));
       /* Omit here local type decls until we know how to support them.  */
-      else if (TREE_CODE (tem) == TYPE_DECL)
+      if (TREE_CODE (tem) == TYPE_DECL
+         /* Omit fields whose position or size are variable or too large to
+            represent.  */
+         || (TREE_CODE (tem) == FIELD_DECL
+             && (! host_integerp (bit_position (tem), 0)
+                 || ! DECL_SIZE (tem)
+                 || ! host_integerp (DECL_SIZE (tem), 1)))
+         /* Omit here the nameless fields that are used to skip bits.  */
+          || DECL_IGNORED_P (tem))
        continue;
-      /* Omit here the nameless fields that are used to skip bits.  */
-      else if (DECL_NAME (tem) != 0 && TREE_CODE (tem) != CONST_DECL)
+
+      else if (TREE_CODE (tem) != CONST_DECL)
        {
          /* Continue the line if necessary,
             but not before the first field.  */
          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))
+         if (DECL_NAME (tem))
+           {
+             fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
+             CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem)));
+           }
+         else
            {
-             have_used_extensions = 1;
-             CHARS (3 + IDENTIFIER_LENGTH (DECL_NAME (TYPE_NAME (DECL_FCONTEXT (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);
-             fprintf (asmfile, ",%d;",
-                      TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));
-             continue;
+             CHARS (1);
            }
 
-         fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
-         CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem)));
-
          if (use_gnu_debug_info_extensions
              && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem)
                  || TREE_CODE (tem) != FIELD_DECL))
@@ -632,34 +779,34 @@ 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)
                {
-                 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;");
+                 CHARS (5);
                }
            }
-         else if (TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)
+         else
            {
-             fprintf (asmfile, ",%d,%d;",
-                      TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)),
-                      TREE_INT_CST_LOW (DECL_SIZE (tem)));
+             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);
            }
-         else
-           /* This has yet to be implemented.  */
-           abort ();
-         CHARS (23);
        }
     }
 }
@@ -672,15 +819,15 @@ dbxout_type_fields (type)
 static void
 dbxout_type_method_1 (decl, debug_name)
      tree decl;
-     char *debug_name;
+     const char *debug_name;
 {
-  tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)));
   char c1 = 'A', c2;
 
   if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
     c2 = '?';
   else /* it's a METHOD_TYPE.  */
     {
+      tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)));
       /* A for normal functions.
         B for `const' member functions.
         C for `volatile' member functions.
@@ -697,16 +844,19 @@ dbxout_type_method_1 (decl, debug_name)
     }
 
   fprintf (asmfile, ":%s;%c%c%c", debug_name,
-          TREE_PRIVATE (decl) ? '0' : TREE_PROTECTED (decl) ? '1' : '2', c1, c2);
+          TREE_PRIVATE (decl) ? '0'
+          : TREE_PROTECTED (decl) ? '1' : '2', c1, c2);
   CHARS (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)) + 6
         - (debug_name - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
-  if (DECL_VINDEX (decl))
+
+  if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0))
     {
-      fprintf (asmfile, "%d;",
-              TREE_INT_CST_LOW (DECL_VINDEX (decl)));
-      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
@@ -715,48 +865,44 @@ dbxout_type_method_1 (decl, debug_name)
 
 static void
 dbxout_type_methods (type)
-     register tree type;
+     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;
 
   type_encoding = DECL_NAME (TYPE_NAME (type));
 
+#if 0
   /* C++: Template classes break some assumptions made by this code about
      the class names, constructor names, and encodings for assembler
      label names.  For now, disable output of dbx info for them.  */
   {
-    char *ptr = IDENTIFIER_POINTER (type_encoding);
+    const char *ptr = IDENTIFIER_POINTER (type_encoding);
     /* This should use index.  (mrs) */
     while (*ptr && *ptr != '<') ptr++;
     if (*ptr != 0)
       {
        static int warned;
        if (!warned)
-         {
            warned = 1;
-#ifdef HAVE_TEMPLATES
-           if (warn_template_debugging)
-             warning ("dbx info for template class methods not yet supported");
-#endif
-         }
        return;
       }
   }
+#endif
 
   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) == FUNCTION_DECL)
+  if (TREE_CODE (methods) != TREE_VEC)
     fndecl = methods;
   else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
     fndecl = TREE_VEC_ELT (methods, 0);
@@ -765,7 +911,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.
@@ -779,70 +924,36 @@ dbxout_type_methods (type)
        {
          /* This is the "mangled" name of the method.
             It encodes the argument types.  */
-         char *debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
-         int destructor = 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;
 
          last = fndecl;
 
-         if (DECL_IGNORED_P (fndecl))
+         /* Also ignore abstract methods; those are only interesting to
+            the DWARF backends.  */
+         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)
            {
-             /* Detect ordinary methods because their mangled names
-                start with the operation name.  */
-             if (!strncmp (IDENTIFIER_POINTER (name), debug_name,
-                           IDENTIFIER_LENGTH (name)))
-               {
-                 debug_name += IDENTIFIER_LENGTH (name);
-                 if (debug_name[0] == '_' && debug_name[1] == '_')
-                   {
-                     char *method_name = debug_name + 2;
-                     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] == '_')
-               {
-                 char *ctor_name = debug_name + 2;
-                 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
-               destructor = 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, destructor);
+         dbxout_type (TREE_TYPE (fndecl), 0);
 
          dbxout_type_method_1 (fndecl, debug_name);
        }
@@ -856,31 +967,64 @@ dbxout_type_methods (type)
 
 /* Emit a "range" type specification, which has the form:
    "r<index type>;<lower bound>;<upper bound>;".
-   TYPE is an INTEGER_TYPE. */
+   TYPE is an INTEGER_TYPE.  */
 
 static void
 dbxout_range_type (type)
      tree type;
 {
   fprintf (asmfile, "r");
-  if (TREE_TYPE (type) && TREE_CODE (TREE_TYPE(type)) != INTEGER_TYPE)
-    dbxout_type (TREE_TYPE (type), 0, 0);
+  if (TREE_TYPE (type))
+    dbxout_type (TREE_TYPE (type), 0);
+  else if (TREE_CODE (type) != INTEGER_TYPE)
+    dbxout_type (type, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
   else
     {
-      /* This used to say `r1' and we used to take care
-        to make sure that `int' was type number 1.  */
-      fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (integer_type_node));
+      /* Traditionally, we made sure 'int' was type 1, and builtin types
+        were defined to be sub-ranges of int.  Unfortunately, this
+        does not allow us to distinguish true sub-ranges from integer
+        types.  So, instead we define integer (non-sub-range) types as
+        sub-ranges of themselves.  This matters for Chill.  If this isn't
+        a subrange type, then we want to define it in terms of itself.
+        However, in C, this may be an anonymous integer type, and we don't
+        want to emit debug info referring to it.  Just calling
+        dbxout_type_index won't work anyways, because the type hasn't been
+        defined yet.  We make this work for both cases by checked to see
+        whether this is a defined type, referring to it if it is, and using
+        'int' otherwise.  */
+      if (TYPE_SYMTAB_ADDRESS (type) != 0)
+       dbxout_type_index (type);
+      else
+       dbxout_type_index (integer_type_node);
+    }
+
+  if (TYPE_MIN_VALUE (type) != 0
+      && host_integerp (TYPE_MIN_VALUE (type), 0))
+    {
+      putc (';', asmfile);
+      CHARS (1);
+      print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
     }
-  if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
-    fprintf (asmfile, ";%d", 
-            TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)));
   else
-    fprintf (asmfile, ";0");
-  if (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST)
-    fprintf (asmfile, ";%d;", 
-            TREE_INT_CST_LOW (TYPE_MAX_VALUE (type)));
+    {
+      fprintf (asmfile, ";0");
+      CHARS (2);
+    }
+
+  if (TYPE_MAX_VALUE (type) != 0
+      && host_integerp (TYPE_MAX_VALUE (type), 0))
+    {
+      putc (';', asmfile);
+      CHARS (1);
+      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
@@ -891,20 +1035,20 @@ 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)
+dbxout_type (type, full)
      tree type;
      int full;
-     int show_arg_types;
 {
-  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);
+
   /* If there was an input error and we don't really have a type,
      avoid crashing and write something that is at least valid
      by assuming `int'.  */
@@ -912,13 +1056,24 @@ dbxout_type (type, full, show_arg_types)
     type = integer_type_node;
   else
     {
-      type = TYPE_MAIN_VARIANT (type);
       if (TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-         && DECL_IGNORED_P (TYPE_NAME (type)))
+         && 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.  */
@@ -928,15 +1083,24 @@ dbxout_type (type, full, show_arg_types)
 
       if (next_type_number == typevec_len)
        {
-         typevec = (enum typestatus *) xrealloc (typevec, typevec_len * 2 * sizeof typevec[0]);
-         bzero (typevec + typevec_len, typevec_len * sizeof typevec[0]);
+         typevec
+           = (struct typeinfo *) xrealloc (typevec,
+                                           typevec_len * 2 * sizeof typevec[0]);
+         memset ((char *) (typevec + typevec_len), 0,
+                typevec_len * sizeof typevec[0]);
          typevec_len *= 2;
        }
+
+#ifdef DBX_USE_BINCL
+      typevec[TYPE_SYMTAB_ADDRESS (type)].file_number
+       = current_file->file_number;
+      typevec[TYPE_SYMTAB_ADDRESS (type)].type_number
+       = current_file->next_type_number++;
+#endif
     }
 
   /* Output the number of this type, to refer to it.  */
-  fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
-  CHARS (3);
+  dbxout_type_index (type);
 
 #ifdef DBX_TYPE_DEFINED
   if (DBX_TYPE_DEFINED (type))
@@ -946,7 +1110,7 @@ dbxout_type (type, full, show_arg_types)
   /* If this type's definition has been output or is now being output,
      that is all.  */
 
-  switch (typevec[TYPE_SYMTAB_ADDRESS (type)])
+  switch (typevec[TYPE_SYMTAB_ADDRESS (type)].status)
     {
     case TYPE_UNSEEN:
       break;
@@ -955,9 +1119,9 @@ dbxout_type (type, full, show_arg_types)
         and either that's all we want or that's the best we could do,
         don't repeat the cross reference.
         Sun dbx crashes if we do.  */
-      if (! full || TYPE_SIZE (type) == 0
+      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:
@@ -967,15 +1131,24 @@ dbxout_type (type, full, show_arg_types)
 #ifdef DBX_NO_XREFS
   /* For systems where dbx output does not allow the `=xsNAME:' syntax,
      leave the type-number completely undefined rather than output
-     a cross-reference.  */
-  if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
-      || TREE_CODE (type) == QUAL_UNION_TYPE
-      || TREE_CODE (type) == ENUMERAL_TYPE)
-
-    if ((TYPE_NAME (type) != 0 && !full)
-       || TYPE_SIZE (type) == 0)
+     a cross-reference.  If we have already used GNU debug info extensions,
+     then it is OK to output a cross reference.  This is necessary to get
+     proper C++ debug output.  */
+  if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
+       || TREE_CODE (type) == QUAL_UNION_TYPE
+       || TREE_CODE (type) == ENUMERAL_TYPE)
+      && ! use_gnu_debug_info_extensions)
+    /* We must use the same test here as we use twice below when deciding
+       whether to emit a cross-reference.  */
+    if ((TYPE_NAME (type) != 0
+        && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+              && DECL_IGNORED_P (TYPE_NAME (type)))
+        && !full)
+       || !COMPLETE_TYPE_P (type)
+       /* No way in DBX fmt to describe a variable size.  */
+       || ! host_integerp (TYPE_SIZE (type), 1))
       {
-       typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+       typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
        return;
       }
 #endif
@@ -988,7 +1161,32 @@ dbxout_type (type, full, show_arg_types)
   /* Mark it as defined, so that if it is self-referent
      we will not get into an infinite recursion of definitions.  */
 
-  typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_DEFINED;
+  typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED;
+
+  /* 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))
+    {
+      /* '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))
     {
@@ -999,67 +1197,144 @@ dbxout_type (type, full, show_arg_types)
         without saying what it is.  The debugger will make it
         a void type when the reference is seen, and nothing will
         ever override that default.  */
-      fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
-      CHARS (3);
+      dbxout_type_index (type);
       break;
 
     case INTEGER_TYPE:
       if (type == char_type_node && ! TREE_UNSIGNED (type))
-       /* Output the type `char' as a subrange of itself!
-          I don't understand this definition, just copied it
-          from the output of pcc.
-          This used to use `r2' explicitly and we used to
-          take care to make sure that `char' was type number 2.  */
-       fprintf (asmfile, "r%d;0;127;", TYPE_SYMTAB_ADDRESS (type));
-      else if (use_gnu_debug_info_extensions
-              && TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node))
        {
-         /* This used to say `r1' and we used to take care
-            to make sure that `int' was type number 1.  */
-         fprintf (asmfile, "r%d;", TYPE_SYMTAB_ADDRESS (integer_type_node));
-         print_int_cst_octal (TYPE_MIN_VALUE (type));
-         fprintf (asmfile, ";");
-         print_int_cst_octal (TYPE_MAX_VALUE (type));
-         fprintf (asmfile, ";");
+         /* Output the type `char' as a subrange of itself!
+            I don't understand this definition, just copied it
+            from the output of pcc.
+            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);
        }
-      else /* Output other integer types as subranges of `int'.  */
+
+      /* 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_TYPE)
        dbxout_range_type (type);
-      CHARS (25);
+
+      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))
+           {
+             have_used_extensions = 1;
+             fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
+             CHARS (5);
+           }
+
+         /* If we can use GDB extensions and the size is wider than a
+            long (the size used by GDB to read them) or we may have
+            trouble writing the bounds the usual way, write them in
+            octal.  Note the test is for the *target's* size of "long",
+            not that of the host.  The host test is just to make sure we
+            can write it out in case the host wide int is narrower than the
+            target "long".  */
+
+         /* For unsigned types, we use octal if they are the same size or
+            larger.  This is because we print the bounds as signed decimal,
+            and hence they can't span same size unsigned types.  */
+
+         if (use_gnu_debug_info_extensions
+             && TYPE_MIN_VALUE (type) != 0
+             && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
+             && TYPE_MAX_VALUE (type) != 0
+             && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
+             && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
+                 || ((TYPE_PRECISION (type)
+                      == TYPE_PRECISION (integer_type_node))
+                     && TREE_UNSIGNED (type))
+                 || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
+                 || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
+                     && TREE_UNSIGNED (type))))
+           {
+             fprintf (asmfile, "r");
+             CHARS (1);
+             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);
+       }
+
       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%d;%d;0;", TYPE_SYMTAB_ADDRESS (integer_type_node),
-              int_size_in_bytes (type));
-      CHARS (16);
+      fprintf (asmfile, "r");
+      CHARS (1);
+      dbxout_type_index (integer_type_node);
+      putc (';', asmfile);
+      CHARS (1);
+      print_wide_int (int_size_in_bytes (type));
+      fputs (";0;", asmfile);
+      CHARS (3);
       break;
 
     case CHAR_TYPE:
       if (use_gnu_debug_info_extensions)
-       fprintf (asmfile, "@s%d;-20;",
-                BITS_PER_UNIT * int_size_in_bytes (type));
+       {
+         have_used_extensions = 1;
+         fputs ("@s", asmfile);
+         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%d;0;%d;", TYPE_SYMTAB_ADDRESS (char_type_node),
-              TREE_UNSIGNED (type) ? 255 : 127);
-      CHARS (9);
+       {
+         /* 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);
+       }
       break;
 
     case BOOLEAN_TYPE:
       if (use_gnu_debug_info_extensions)
-       fprintf (asmfile, "@s%d;-16;",
-                BITS_PER_UNIT * int_size_in_bytes (type));
+       {
+         have_used_extensions = 1;
+         fputs ("@s", asmfile);
+         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:
@@ -1067,55 +1342,103 @@ dbxout_type (type, full, show_arg_types)
 
       if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
        {
-         fprintf (asmfile, "r%d;%d;0;",
-                  TYPE_SYMTAB_ADDRESS (type),
-                  int_size_in_bytes (TREE_TYPE (type)));
-         CHARS (15);           /* The number is probably incorrect here.  */
+         fprintf (asmfile, "r");
+         CHARS (1);
+         dbxout_type_index (type);
+         putc (';', asmfile);
+         CHARS (1);
+         print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
+         fputs (";0;", asmfile);
+         CHARS (3);
        }
       else
        {
          /* Output a complex integer type as a structure,
             pending some other way to do it.  */
-         fprintf (asmfile, "s%d", 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;
 
     case SET_TYPE:
+      if (use_gnu_debug_info_extensions)
+       {
+         have_used_extensions = 1;
+         fputs ("@s", 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;");
+             CHARS (3);
+           }
+       }
       putc ('S', asmfile);
       CHARS (1);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+      dbxout_type (TYPE_DOMAIN (type), 0);
       break;
 
     case ARRAY_TYPE:
+      /* Make arrays of packed bits look like bitstrings for chill.  */
+      if (TYPE_PACKED (type) && use_gnu_debug_info_extensions)
+       {
+         have_used_extensions = 1;
+         fputs ("@s", asmfile);
+         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.
         ar1;0;N;M for a C array of type M and size N+1.  */
+      /* Check if a character string type, which in Chill is
+        different from an array of characters.  */
+      if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
+       {
+         have_used_extensions = 1;
+         fprintf (asmfile, "@S;");
+         CHARS (3);
+       }
       tem = TYPE_DOMAIN (type);
       if (tem == NULL)
-       fprintf (asmfile, "ar%d;0;-1;",
-                TYPE_SYMTAB_ADDRESS (integer_type_node));
+       {
+         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 (17);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case RECORD_TYPE:
@@ -1124,23 +1447,20 @@ dbxout_type (type, full, show_arg_types)
       {
        int i, n_baseclasses = 0;
 
-       if (TYPE_BINFO (type) != 0 && TYPE_BINFO_BASETYPES (type) != 0)
+       if (TYPE_BINFO (type) != 0
+           && TREE_CODE (TYPE_BINFO (type)) == TREE_VEC
+           && TYPE_BINFO_BASETYPES (type) != 0)
          n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
 
-       /* Output a structure type.  */
+       /* Output a structure type.  We must use the same test here as we
+          use in the DBX_NO_XREFS case above.  */
        if ((TYPE_NAME (type) != 0
-            /* Long ago, Tiemann said this creates output that "confuses GDB".
-               In April 93, mrs@cygnus.com said there is no such problem.
-               The type decls made automatically by struct specifiers
-               are marked with DECL_IGNORED_P in C++.  */
-#if 0 /* This creates output for anonymous classes which confuses GDB. */
             && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
                   && DECL_IGNORED_P (TYPE_NAME (type)))
-#endif
             && !full)
-           || TYPE_SIZE (type) == 0
+           || !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.
@@ -1149,8 +1469,8 @@ dbxout_type (type, full, show_arg_types)
               If the type has a name, don't nest its definition within
               another type's definition; instead, output an xref
               and let the definition come when the name is defined.  */
-           fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
-           CHARS (3);
+           fputs ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu", asmfile);
+           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.
@@ -1161,15 +1481,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, ":");
-           typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+           CHARS (1);
+           typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
            break;
          }
 
        /* Identify record or union, and print its size.  */
-       fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "s%d" : "u%d",
-                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)
          {
@@ -1183,20 +1509,27 @@ 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);
+
            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, "%d,",
-                        TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT);
-               CHARS (15);
-               dbxout_type (BINFO_TYPE (child), 0, 0);
+               putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
+               putc (TREE_VIA_PUBLIC (child) ? '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
              {
@@ -1204,17 +1537,25 @@ 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);
-               fprintf (asmfile, ",%d,%d;",
-                        TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT,
-                        TREE_INT_CST_LOW (DECL_SIZE (TYPE_NAME (BINFO_TYPE (child)))) * BITS_PER_UNIT);
-               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 (DECL_SIZE
+                                             (TYPE_NAME
+                                              (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)
@@ -1222,7 +1563,9 @@ dbxout_type (type, full, show_arg_types)
          have_used_extensions = 1;
          dbxout_type_methods (type);
        }
+
       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.  */
@@ -1232,6 +1575,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
@@ -1240,48 +1584,63 @@ 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;
 
     case ENUMERAL_TYPE:
-      if ((TYPE_NAME (type) != 0 && !full
-          && (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-              && ! DECL_IGNORED_P (TYPE_NAME (type))))
-         || TYPE_SIZE (type) == 0)
+      /* We must use the same test here as we use in the DBX_NO_XREFS case
+        above.  We simplify it a bit since an enum will never have a variable
+        size.  */
+      if ((TYPE_NAME (type) != 0
+          && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+                && DECL_IGNORED_P (TYPE_NAME (type)))
+          && !full)
+         || !COMPLETE_TYPE_P (type))
        {
          fprintf (asmfile, "xe");
-         CHARS (3);
+         CHARS (2);
          dbxout_type_name (type);
-         typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
-         fprintf (asmfile, ":");
+         typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
+         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));
+         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)
-           {
-             if (TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)
-               fprintf (asmfile, "%u", TREE_INT_CST_LOW (TREE_VALUE (tem)));
-             else
-               fprintf (asmfile, "%d", 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)
+           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;
        }
+
       putc (';', asmfile);
       CHARS (1);
 #endif
@@ -1290,7 +1649,7 @@ dbxout_type (type, full, show_arg_types)
     case POINTER_TYPE:
       putc ('*', asmfile);
       CHARS (1);
-      dbxout_type (TREE_TYPE (type), 0, 0);
+      dbxout_type (TREE_TYPE (type), 0);
       break;
 
     case METHOD_TYPE:
@@ -1299,33 +1658,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);
-             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:
@@ -1334,17 +1679,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:
@@ -1352,13 +1694,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:
@@ -1376,8 +1718,22 @@ print_int_cst_octal (c)
   unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c);
   unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c);
   int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3));
+  unsigned int width = TYPE_PRECISION (TREE_TYPE (c));
+
+  /* GDB wants constants with no extra leading "1" bits, so
+     we need to remove any sign-extension that might be
+     present.  */
+  if (width == HOST_BITS_PER_WIDE_INT * 2)
+    ;
+  else if (width > HOST_BITS_PER_WIDE_INT)
+    high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
+  else if (width == HOST_BITS_PER_WIDE_INT)
+    high = 0;
+  else
+    high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
 
   fprintf (asmfile, "0");
+  CHARS (1);
 
   if (excess == 3)
     {
@@ -1391,8 +1747,12 @@ print_int_cst_octal (c)
        = ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess)
           | (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3)));
       unsigned HOST_WIDE_INT end
-       = low & (((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 3 * 3)) - 1);
-      fprintf (asmfile, "%o%01o", beg, middle);
+       = low & (((unsigned HOST_WIDE_INT) 1
+                 << (HOST_BITS_PER_WIDE_INT / 3 * 3))
+                - 1);
+
+      fprintf (asmfile, "%o%01o", (int) beg, (int) middle);
+      CHARS (2);
       print_octal (end, HOST_BITS_PER_WIDE_INT / 3);
     }
 }
@@ -1405,16 +1765,37 @@ print_octal (value, digits)
   int i;
 
   for (i = digits - 1; i >= 0; i--)
-    fprintf (asmfile, "%01o", ((value >> (3 * i)) & 7));
+    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 (c)
+     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.
    Such names can be set up either by typedef declarations
    or by struct, enum and union tags.  */
 
 static void
 dbxout_type_name (type)
-     register tree type;
+     tree type;
 {
   tree t;
   if (TYPE_NAME (type) == 0)
@@ -1437,17 +1818,17 @@ dbxout_type_name (type)
 /* Output a .stabs for the symbol defined by DECL,
    which must be a ..._DECL node in the normal namespace.
    It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
-   LOCAL is nonzero if the scope is less than the entire file.  */
+   LOCAL is nonzero if the scope is less than the entire file.
+   Return 1 if a stabs might have been emitted.  */
 
-void
+int
 dbxout_symbol (decl, local)
      tree decl;
-     int local;
+     int local ATTRIBUTE_UNUSED;
 {
-  int letter = 0;
   tree type = TREE_TYPE (decl);
   tree context = NULL_TREE;
-  int regno = -1;
+  int result = 0;
 
   /* Cast avoids warning in old compilers.  */
   current_sym_code = (STAB_CODE_TYPE) 0;
@@ -1458,7 +1839,7 @@ dbxout_symbol (decl, local)
 
   if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)
       || DECL_IGNORED_P (decl))
-    return;
+    return 0;
 
   dbxout_prepare_symbol (decl);
 
@@ -1476,7 +1857,7 @@ dbxout_symbol (decl, local)
 
     case FUNCTION_DECL:
       if (DECL_RTL (decl) == 0)
-       return;
+       return 0;
       if (DECL_EXTERNAL (decl))
        break;
       /* Don't mention a nested function under its parent.  */
@@ -1488,17 +1869,18 @@ dbxout_symbol (decl, local)
        break;
       FORCE_TEXT;
 
-      fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,
+      fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
               IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
               TREE_PUBLIC (decl) ? 'F' : 'f');
+      result = 1;
 
       current_sym_code = N_FUN;
       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
@@ -1520,17 +1902,17 @@ dbxout_symbol (decl, local)
 
       /* If this typedef name was defined by outputting the type,
         don't duplicate it.  */
-      if (typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED
+      if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED
          && TYPE_NAME (TREE_TYPE (decl)) == decl)
-       return;
+       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) || DECL_IGNORED_P (decl))
-       return;
+      if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
+       return 0;
 
       FORCE_TEXT;
-
+      result = 1;
       {
        int tag_needed = 1;
        int did_output = 0;
@@ -1552,7 +1934,11 @@ 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_SOURCE_LINE (decl) == 0)
+                && DECL_ARTIFICIAL (decl)
+               /* 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)
@@ -1563,21 +1949,24 @@ dbxout_symbol (decl, local)
                current_sym_addr = 0;
                current_sym_nchars = 2 + IDENTIFIER_LENGTH (name);
 
-               fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP,
+               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 typedef name.  */
-           fprintf (asmfile, "%s \"%s:", ASM_STABS_OP,
+           fprintf (asmfile, "%s\"%s:", ASM_STABS_OP,
                     IDENTIFIER_POINTER (DECL_NAME (decl)));
 
            /* Short cut way to output a tag also.  */
            if ((TREE_CODE (type) == RECORD_TYPE
                 || TREE_CODE (type) == UNION_TYPE
                 || TREE_CODE (type) == QUAL_UNION_TYPE)
-               && TYPE_NAME (type) == decl)
+               && TYPE_NAME (type) == decl
+               /* Distinguish the implicit typedefs of C++
+                  from explicit ones that might be found in C.  */
+                && DECL_ARTIFICIAL (decl))
              {
                if (use_gnu_debug_info_extensions && have_used_extensions)
                  {
@@ -1593,15 +1982,18 @@ 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 && TYPE_SIZE (type) != 0
+       if (tag_needed && TYPE_NAME (type) != 0
+           && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE
+               || (DECL_NAME (TYPE_NAME (type)) != 0))
+           && COMPLETE_TYPE_P (type)
            && !TREE_ASM_WRITTEN (TYPE_NAME (type)))
          {
            /* For a TYPE_DECL with no name, but the type has a name,
@@ -1618,9 +2010,9 @@ dbxout_symbol (decl, local)
            current_sym_addr = 0;
            current_sym_nchars = 2 + IDENTIFIER_LENGTH (name);
 
-           fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP,
+           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;
          }
@@ -1637,8 +2029,8 @@ 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);
+           fprintf (asmfile, "%s\" :T", ASM_STABS_OP);
+           dbxout_type (type, 1);
            dbxout_finish_symbol (NULL_TREE);
          }
 
@@ -1655,8 +2047,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;
+      if (! DECL_RTL_SET_P (decl))
+       return 0;
       /* Don't mention a variable that is external.
         Let the file that defines it describe it.  */
       if (DECL_EXTERNAL (decl))
@@ -1666,25 +2058,29 @@ dbxout_symbol (decl, local)
         and not written in memory, inform the debugger.  */
       if (TREE_STATIC (decl) && TREE_READONLY (decl)
          && DECL_INITIAL (decl) != 0
+         && host_integerp (DECL_INITIAL (decl), 0)
          && ! TREE_ASM_WRITTEN (decl)
-         && (DECL_FIELD_CONTEXT (decl) == NULL_TREE
-             || TREE_CODE (DECL_FIELD_CONTEXT (decl)) == BLOCK))
+         && (DECL_CONTEXT (decl) == NULL_TREE
+             || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK))
        {
          if (TREE_PUBLIC (decl) == 0)
            {
              /* The sun4 assembler does not grok this.  */
-             char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+             const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+
              if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
                  || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
                {
-                 HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
+                 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%d\",0x%x,0,0,0\n",
-                          ASM_STABS_OP, name, ival, N_LSYM);
+                 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
-                 return;
+                 return 1;
                }
              else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE)
                {
@@ -1695,25 +2091,31 @@ dbxout_symbol (decl, local)
          /* else it is something we handle like a normal variable.  */
        }
 
-      DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+      SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
 #ifdef LEAF_REG_REMAP
-      if (leaf_function)
+      if (current_function_uses_only_leaf_regs)
        leaf_renumber_regs_insn (DECL_RTL (decl));
 #endif
 
-      dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+      result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+      break;
+      
+    default:
+      break;
     }
+  return result;
 }
 \f
 /* Output the stab for DECL, a VAR_DECL, RESULT_DECL or PARM_DECL.
    Add SUFFIX to its name, if SUFFIX is not 0.
    Describe the variable as residing in HOME
-   (usually HOME is DECL_RTL (DECL), but not always).  */
+   (usually HOME is DECL_RTL (DECL), but not always).
+   Returns 1 if the stab was really emitted.  */
 
-static void
+static int
 dbxout_symbol_location (decl, type, suffix, home)
      tree decl, type;
-     char *suffix;
+     const char *suffix;
      rtx home;
 {
   int letter = 0;
@@ -1722,32 +2124,27 @@ dbxout_symbol_location (decl, type, suffix, home)
   /* Don't mention a variable at all
      if it was completely optimized into nothingness.
      
-     If the decl was from an inline function, then it's rtl
+     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;
-    }
-  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)
-           return;
-         regno += offset;
+         if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
+           return 0;
        }
-      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
@@ -1777,14 +2174,35 @@ dbxout_symbol_location (decl, type, suffix, home)
 
          letter = decl_function_context (decl) ? 'V' : 'S';
 
-         if (!DECL_INITIAL (decl))
+         /* This should be the same condition as in assemble_variable, but
+            we don't have access to dont_output_data here.  So, instead,
+            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_hooks.name, "GNU C++")
+                 && DECL_INITIAL (decl) == error_mark_node))
            current_sym_code = N_LCSYM;
-         else if (in_text_section ())
+         else if (DECL_IN_TEXT_SECTION (decl))
            /* This is not quite right, but it's the closest
               of all the codes that Unix defines.  */
            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 ();
@@ -1802,7 +2220,12 @@ dbxout_symbol_location (decl, type, suffix, home)
   else if (GET_CODE (home) == MEM
           && (GET_CODE (XEXP (home, 0)) == MEM
               || (GET_CODE (XEXP (home, 0)) == REG
-                  && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM)))
+                  && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+                  && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+                  && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+#endif
+                  )))
     /* If the value is indirect by memory or by a register
        that isn't the frame pointer
        then it means the object is variable-sized and address through
@@ -1815,6 +2238,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
@@ -1868,7 +2293,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.  */
@@ -1887,13 +2320,13 @@ dbxout_symbol_location (decl, type, suffix, home)
        dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1));
       else
        dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1));
-      return;
+      return 1;
     }
   else
     /* Address might be a MEM, when DECL is a variable-sized object.
        Or it might be const0_rtx, meaning previous passes
        want us to ignore this variable.  */
-    return;
+    return 0;
 
   /* Ok, start a symtab entry and output the variable name.  */
   FORCE_TEXT;
@@ -1903,12 +2336,13 @@ 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
   DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
 #endif
+  return 1;
 }
 \f
 /* Output the symbol name of DECL for a stabs, with suffix SUFFIX.
@@ -1917,34 +2351,37 @@ dbxout_symbol_location (decl, type, suffix, home)
 static void
 dbxout_symbol_name (decl, suffix, letter)
      tree decl;
-     char *suffix;
+     const char *suffix;
      int letter;
 {
-  /* One slight hitch: if this is a VAR_DECL which is a static
-     class member, we must put out the mangled name instead of the
-     DECL_NAME.  */
-
-  char *name;
-  /* Note also that static member (variable) names DO NOT begin
-     with underscores in .stabs directives.  */
-  if (DECL_LANG_SPECIFIC (decl))
+  const char *name;
+
+  if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+    /* One slight hitch: if this is a VAR_DECL which is a static
+       class member, we must put out the mangled name instead of the
+       DECL_NAME.  Note also that static member (variable) names DO NOT begin
+       with underscores in .stabs directives.  */
     name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   else
+    /* ...but if we're function-local, we don't want to include the junk
+       added by ASM_FORMAT_PRIVATE_NAME.  */
     name = IDENTIFIER_POINTER (DECL_NAME (decl));
+
   if (name == 0)
     name = "(anon)";
-  fprintf (asmfile, "%s \"%s%s:", ASM_STABS_OP, name,
+  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;
+     tree decl ATTRIBUTE_UNUSED;
 {
 #ifdef WINNING_GDB
-  char *filename = DECL_SOURCE_FILE (decl);
+  const char *filename = DECL_SOURCE_FILE (decl);
 
   dbxout_source_file (asmfile, filename);
 #endif
@@ -1970,17 +2407,20 @@ dbxout_finish_symbol (sym)
 #endif
 }
 
-/* Output definitions of all the decls in a chain.  */
+/* Output definitions of all the decls in a chain. Return non-zero if
+   anything was output */
 
-void
+int
 dbxout_syms (syms)
      tree syms;
 {
+  int result = 0;
   while (syms)
     {
-      dbxout_symbol (syms, 1);
+      result += dbxout_symbol (syms, 1);
       syms = TREE_CHAIN (syms);
     }
+  return result;
 }
 \f
 /* The following two functions output definitions of function parameters.
@@ -2008,9 +2448,9 @@ dbxout_parms (parms)
           so that the debugging output will be accurate.  */
        DECL_INCOMING_RTL (parms)
          = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
-       DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
+       SET_DECL_RTL (parms, eliminate_regs (DECL_RTL (parms), 0, NULL_RTX));
 #ifdef LEAF_REG_REMAP
-       if (leaf_function)
+       if (current_function_uses_only_leaf_regs)
          {
            leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
            leaf_renumber_regs_insn (DECL_RTL (parms));
@@ -2039,48 +2479,32 @@ dbxout_parms (parms)
              {
                current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
 
-               fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,
+               fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
                         IDENTIFIER_POINTER (DECL_NAME (parms)),
                         DBX_MEMPARM_STABS_LETTER);
              }
            else
              {
                current_sym_nchars = 8;
-               fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,
+               fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
                         DBX_MEMPARM_STABS_LETTER);
              }
 
-           if (GET_CODE (DECL_RTL (parms)) == REG
-               && REGNO (DECL_RTL (parms)) >= 0
-               && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
-             dbxout_type (DECL_ARG_TYPE (parms), 0, 0);
-           else
-             {
-               int original_value = current_sym_value;
-
-               /* This is the case where the parm is passed as an int or double
-                  and it is converted to a char, short or float and stored back
-                  in the parmlist.  In this case, describe the parm
-                  with the variable's declared type, and adjust the address
-                  if the least significant bytes (which we are using) are not
-                  the first ones.  */
-#if BYTES_BIG_ENDIAN
-               if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
-                 current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
-                                       - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
-#endif
-
-               if (GET_CODE (DECL_RTL (parms)) == MEM
-                   && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
-                   && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
-                   && INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value)
-                 dbxout_type (TREE_TYPE (parms), 0, 0);
-               else
-                 {
-                   current_sym_value = original_value;
-                   dbxout_type (DECL_ARG_TYPE (parms), 0, 0);
-                 }
-             }
+           /* It is quite tempting to use:
+              
+                  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
+              than the promoted type.  This certainly makes GDB's life
+              easier, at least for some ports.  The change is a bad idea
+              however, since GDB expects to be able access the type without
+              performing any conversions.  So for example, if we were
+              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 erroneous value.  */
+           dbxout_type (DECL_ARG_TYPE (parms), 0);
            current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
            dbxout_finish_symbol (parms);
          }
@@ -2102,18 +2526,17 @@ dbxout_parms (parms)
 
               If we use DECL_RTL, then we must use the declared type of
               the variable, not the type that it arrived in.  */
-           if (REGNO (DECL_RTL (parms)) >= 0
-               && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
+           if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
              {
                best_rtl = DECL_RTL (parms);
                parm_type = TREE_TYPE (parms);
              }
-           /* If the parm lives nowhere,
-              use the register where it was passed.  */
+           /* If the parm lives nowhere, use the register where it was
+              passed.  It is also better to use the declared type here.  */
            else
              {
                best_rtl = DECL_INCOMING_RTL (parms);
-               parm_type = DECL_ARG_TYPE (parms);
+               parm_type = TREE_TYPE (parms);
              }
            current_sym_value = DBX_REGISTER_NUMBER (REGNO (best_rtl));
 
@@ -2121,24 +2544,28 @@ dbxout_parms (parms)
            if (DECL_NAME (parms))
              {
                current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
-               fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,
+               fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
                         IDENTIFIER_POINTER (DECL_NAME (parms)),
                         regparm_letter);
              }
            else
              {
                current_sym_nchars = 8;
-               fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,
+               fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
                         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
                 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
-                && (REGNO (XEXP (DECL_RTL (parms), 0))
-                    >= FIRST_PSEUDO_REGISTER))
+                && REGNO (XEXP (DECL_RTL (parms), 0)) != HARD_FRAME_POINTER_REGNUM
+                && REGNO (XEXP (DECL_RTL (parms), 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+                && REGNO (XEXP (DECL_RTL (parms), 0)) != ARG_POINTER_REGNUM
+#endif
+                )
          {
            /* Parm was passed via invisible reference.
               That is, its address was passed in a register.
@@ -2150,29 +2577,65 @@ dbxout_parms (parms)
            /* Parm passed in registers and lives in registers or nowhere.  */
 
            current_sym_code = DBX_REGPARM_STABS_CODE;
-           regparm_letter = DBX_REGPARM_STABS_LETTER;
+           if (use_gnu_debug_info_extensions)
+             regparm_letter = GDB_INV_REF_REGPARM_STABS_LETTER;
+           else
+             regparm_letter = DBX_REGPARM_STABS_LETTER;
+
+           /* DECL_RTL looks like (MEM (REG...).  Get the register number.
+              If it is an unallocated pseudo-reg, then use the register where
+              it was passed instead.  */
+           if (REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER)
+             current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0));
+           else
+             current_sym_value = REGNO (DECL_INCOMING_RTL (parms));
 
-           /* DECL_RTL looks like (MEM (REG...).  Get the register number.  */
-           current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0));
            current_sym_addr = 0;
 
            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,
+               fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
                         IDENTIFIER_POINTER (DECL_NAME (parms)),
-                        DBX_REGPARM_STABS_LETTER);
+                        regparm_letter);
              }
            else
              {
                current_sym_nchars = 8;
-               fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,
-                        DBX_REGPARM_STABS_LETTER);
+               fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
+                        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
+                && GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
+         {
+           /* Parm was passed via invisible reference, with the reference
+              living on the stack.  DECL_RTL looks like
+              (MEM (MEM (PLUS (REG ...) (CONST_INT ...)))) or it
+              could look like (MEM (MEM (REG))).  */
+           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;
+           else
+             current_sym_value
+               = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
+           current_sym_addr = 0;
+             
+           FORCE_TEXT;
+           fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
+
+           current_sym_value
+             = DEBUGGER_ARG_OFFSET (current_sym_value,
+                                    XEXP (XEXP (DECL_RTL (parms), 0), 0));
+           dbxout_type (TREE_TYPE (parms), 0);
            dbxout_finish_symbol (parms);
          }
        else if (GET_CODE (DECL_RTL (parms)) == MEM
@@ -2187,35 +2650,48 @@ dbxout_parms (parms)
            current_sym_code = N_PSYM;
            /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
               in which case we want the value of that CONST_INT,
-              or (MEM (REG ...)) or (MEM (MEM ...)),
+              or (MEM (REG ...)),
               in which case we use a value of zero.  */
-           if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
-               || GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
+           if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)
              current_sym_value = 0;
            else
-             current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
+               current_sym_value
+                 = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
+
            current_sym_addr = 0;
 
+           /* Make a big endian correction if the mode of the type of the
+              parameter is not the same as the mode of the rtl.  */
+           if (BYTES_BIG_ENDIAN
+               && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
+               && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
+             {
+               current_sym_value += 
+                   GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
+                   - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (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,
+               fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
                         IDENTIFIER_POINTER (DECL_NAME (parms)),
                         DBX_MEMPARM_STABS_LETTER);
              }
            else
              {
                current_sym_nchars = 8;
-               fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,
+               fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
                DBX_MEMPARM_STABS_LETTER);
              }
 
            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);
          }
       }
@@ -2237,115 +2713,43 @@ dbxout_reg_parms (parms)
      tree parms;
 {
   for (; parms; parms = TREE_CHAIN (parms))
-    if (DECL_NAME (parms))
+    if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms))
       {
        dbxout_prepare_symbol (parms);
 
        /* Report parms that live in registers during the function
           but were passed in memory.  */
        if (GET_CODE (DECL_RTL (parms)) == REG
-           && REGNO (DECL_RTL (parms)) >= 0
-           && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
-           && PARM_PASSED_IN_MEMORY (parms))
+           && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
          dbxout_symbol_location (parms, TREE_TYPE (parms),
                                  0, DECL_RTL (parms));
-       else if (GET_CODE (DECL_RTL (parms)) == CONCAT
-                && PARM_PASSED_IN_MEMORY (parms))
+       else if (GET_CODE (DECL_RTL (parms)) == CONCAT)
          dbxout_symbol_location (parms, TREE_TYPE (parms),
                                  0, DECL_RTL (parms));
        /* Report parms that live in memory but not where they were passed.  */
        else if (GET_CODE (DECL_RTL (parms)) == MEM
-                && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
-                && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
-                && PARM_PASSED_IN_MEMORY (parms)
                 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
-         {
-#if 0 /* ??? It is not clear yet what should replace this.  */
-           int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
-           /* A parm declared char is really passed as an int,
-              so it occupies the least significant bytes.
-              On a big-endian machine those are not the low-numbered ones.  */
-#if BYTES_BIG_ENDIAN
-           if (offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
-             offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
-                        - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
-#endif
-           if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
-#endif
-           dbxout_symbol_location (parms, TREE_TYPE (parms),
-                                   0, DECL_RTL (parms));
-         }
-#if 0
-       else if (GET_CODE (DECL_RTL (parms)) == MEM
-                && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)
-         {
-           /* Parm was passed via invisible reference.
-              That is, its address was passed in a register.
-              Output it as if it lived in that register.
-              The debugger will know from the type
-              that it was actually passed by invisible reference.  */
-
-           current_sym_code = N_RSYM;
-
-           /* DECL_RTL looks like (MEM (REG...).  Get the register number.  */
-           current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0));
-           current_sym_addr = 0;
-
-           FORCE_TEXT;
-           if (DECL_NAME (parms))
-             {
-               current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
-
-               fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP,
-                        IDENTIFIER_POINTER (DECL_NAME (parms)));
-             }
-           else
-             {
-               current_sym_nchars = 8;
-               fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP);
-             }
-
-           dbxout_type (TREE_TYPE (parms), 0, 0);
-           dbxout_finish_symbol (parms);
-         }
-#endif
+         dbxout_symbol_location (parms, TREE_TYPE (parms),
+                                 0, DECL_RTL (parms));
       }
 }
 \f
 /* Given a chain of ..._TYPE nodes (as come in a parameter list),
    output definitions of those names, in raw form */
 
-void
+static void
 dbxout_args (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.
@@ -2365,21 +2769,35 @@ dbxout_types (types)
 
 static void
 dbxout_block (block, depth, args)
-     register tree block;
+     tree block;
      int depth;
      tree args;
 {
-  int blocknum;
+  int blocknum = -1;
+
+#if DBX_BLOCKS_FUNCTION_RELATIVE
+  const char *begin_label; 
+  if (current_function_func_begin_label != NULL_TREE)
+    begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
+  else
+    begin_label = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+#endif
 
   while (block)
     {
       /* Ignore blocks never expanded or otherwise marked as real.  */
-      if (TREE_USED (block))
+      if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
        {
-#ifndef DBX_LBRAC_FIRST
-         /* In dbx format, the syms of a block come before the N_LBRAC.  */
+         int did_output;
+
+#ifdef DBX_LBRAC_FIRST
+         did_output = 1;
+#else
+         /* In dbx format, the syms of a block come before the N_LBRAC.
+            If nothing is output, we don't need the N_LBRAC, either.  */
+         did_output = 0;
          if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
-           dbxout_syms (BLOCK_VARS (block));
+           did_output = dbxout_syms (BLOCK_VARS (block));
          if (args)
            dbxout_reg_parms (args);
 #endif
@@ -2388,10 +2806,10 @@ dbxout_block (block, depth, args)
             the block.  Use the block's tree-walk order to generate
             the assembler symbols LBBn and LBEn
             that final will define around the code in this block.  */
-         if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE)
+         if (depth > 0 && did_output)
            {
              char buf[20];
-             blocknum = next_block_number++;
+             blocknum = BLOCK_NUMBER (block);
              ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum);
 
              if (BLOCK_HANDLER_BLOCK (block))
@@ -2403,7 +2821,7 @@ dbxout_block (block, depth, args)
 #ifdef DBX_OUTPUT_CATCH
                      DBX_OUTPUT_CATCH (asmfile, decl, buf);
 #else
-                     fprintf (asmfile, "%s \"%s:C1\",%d,0,0,", ASM_STABS_OP,
+                     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");
@@ -2415,18 +2833,15 @@ dbxout_block (block, depth, args)
 #ifdef DBX_OUTPUT_LBRAC
              DBX_OUTPUT_LBRAC (asmfile, buf);
 #else
-             fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_LBRAC);
+             fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_LBRAC);
              assemble_name (asmfile, buf);
 #if DBX_BLOCKS_FUNCTION_RELATIVE
-             fputc ('-', asmfile);
-             assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+             putc ('-', asmfile);
+             assemble_name (asmfile, begin_label);
 #endif
              fprintf (asmfile, "\n");
 #endif
            }
-         else if (depth > 0)
-           /* Count blocks the same way regardless of debug_info_level.  */
-           next_block_number++;
 
 #ifdef DBX_LBRAC_FIRST
          /* On some weird machines, the syms of a block
@@ -2441,18 +2856,18 @@ dbxout_block (block, depth, args)
          dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
 
          /* Refer to the marker for the end of the block.  */
-         if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE)
+         if (depth > 0 && did_output)
            {
              char buf[20];
              ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum);
 #ifdef DBX_OUTPUT_RBRAC
              DBX_OUTPUT_RBRAC (asmfile, buf);
 #else
-             fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_RBRAC);
+             fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_RBRAC);
              assemble_name (asmfile, buf);
 #if DBX_BLOCKS_FUNCTION_RELATIVE
-             fputc ('-', asmfile);
-             assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+             putc ('-', asmfile);
+             assemble_name (asmfile, begin_label);
 #endif
              fprintf (asmfile, "\n");
 #endif
@@ -2466,8 +2881,9 @@ 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)
+dbxout_begin_function (decl)
      tree decl;
 {
   dbxout_symbol (decl, 0);
@@ -2475,34 +2891,6 @@ dbxout_really_begin_function (decl)
   if (DECL_NAME (DECL_RESULT (decl)) != 0)
     dbxout_symbol (DECL_RESULT (decl), 1);
 }
-
-/* Called at beginning of output of function definition.  */
-
-void
-dbxout_begin_function (decl)
-     tree decl;
-{
-#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
-}
 #endif /* DBX_DEBUGGING_INFO */
+
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */