OSDN Git Service

2003-06-10 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / dbxout.c
index 0a1ced6..7b13e3b 100644 (file)
@@ -1,6 +1,6 @@
 /* Output dbx-format symbol table information from GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -70,6 +70,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "tree.h"
 #include "rtl.h"
@@ -85,6 +87,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "debug.h"
 #include "function.h"
 #include "target.h"
+#include "langhooks.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"
@@ -134,65 +137,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define STABS_GCC_MARKER "gcc2_compiled."
 #endif
 
-/* Typical USG systems don't have stab.h, and they also have
-   no use for DBX-format debugging info.  */
-
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-
-/* Nonzero if we have actually used any of the GDB extensions
-   to the debugging format.  The idea is that we use them for the
-   first time only if there's a strong reason, but once we have done that,
-   we use them whenever convenient.  */
-
-static int have_used_extensions = 0;
-
-/* Number for the next N_SOL filename stabs label.  The number 0 is reserved
-   for the N_SO filename stabs label.  */
-
-#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
-static int source_label_number = 1;
-#endif
-
-#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT text_section ();
-#else
-#define FORCE_TEXT
-#endif
-
-#include "gstab.h"
-
-#define STAB_CODE_TYPE enum __stab_debug_code
-
-/* 1 if PARM is passed to this function in memory.  */
-
-#define PARM_PASSED_IN_MEMORY(PARM) \
- (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
-
-/* A C expression for the integer offset value of an automatic variable
-   (N_LSYM) having address X (an RTX).  */
-#ifndef DEBUGGER_AUTO_OFFSET
-#define DEBUGGER_AUTO_OFFSET(X) \
-  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
-#endif
-
-/* A C expression for the integer offset value of an argument (N_PSYM)
-   having address X (an RTX).  The nominal offset is OFFSET.  */
-#ifndef DEBUGGER_ARG_OFFSET
-#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
-#endif
-
-/* Stream for writing to assembler file.  */
-
-static FILE *asmfile;
-
-/* Last source file name mentioned in a NOTE insn.  */
-
-static const char *lastfile;
-
-/* Current working directory.  */
-
-static const char *cwd;
-
 enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
 
 /* Structure recording information about a C data type.
@@ -202,13 +146,11 @@ enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
    The file_number and type_number elements are used if DBX_USE_BINCL
    is defined.  */
 
-struct typeinfo
+struct typeinfo GTY(())
 {
   enum typestatus status;
-#ifdef DBX_USE_BINCL
   int file_number;
   int type_number;
-#endif
 };
 
 /* Vector recording information about C data types.
@@ -216,25 +158,23 @@ struct typeinfo
    we assign it a number using next_type_number.
    That is its index in this vector.  */
 
-struct typeinfo *typevec;
+static GTY ((length ("typevec_len"))) struct typeinfo *typevec;
 
 /* Number of elements of space allocated in `typevec'.  */
 
-static int typevec_len;
+static GTY(()) int typevec_len;
 
 /* In dbx output, each type gets a unique number.
    This is the number for the next type output.
    The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field.  */
 
-static int next_type_number;
-
-#ifdef DBX_USE_BINCL
+static GTY(()) int next_type_number;
 
 /* When using N_BINCL in dbx output, each type number is actually a
    pair of the file number and the type number within the file.
    This is a stack of input files.  */
 
-struct dbx_file
+struct dbx_file GTY(())
 {
   struct dbx_file *next;
   int file_number;
@@ -243,13 +183,79 @@ struct dbx_file
 
 /* This is the top of the stack.  */
 
-static struct dbx_file *current_file;
+static GTY(()) struct dbx_file *current_file;
 
 /* This is the next file number to use.  */
 
-static int next_file_number;
+static GTY(()) int next_file_number;
+
+/* A counter for dbxout_function_end.  */
+
+static GTY(()) int scope_labelno;
+
+/* Nonzero if we have actually used any of the GDB extensions
+   to the debugging format.  The idea is that we use them for the
+   first time only if there's a strong reason, but once we have done that,
+   we use them whenever convenient.  */
 
-#endif /* DBX_USE_BINCL */
+static GTY(()) int have_used_extensions = 0;
+
+/* Number for the next N_SOL filename stabs label.  The number 0 is reserved
+   for the N_SO filename stabs label.  */
+
+static GTY(()) int source_label_number = 1;
+
+/* Last source file name mentioned in a NOTE insn.  */
+
+static GTY(()) const char *lastfile;
+
+/* Used by PCH machinery to detect if 'lastfile' should be reset to
+   base_input_file.  */
+static GTY(()) int lastfile_is_base;
+
+/* Typical USG systems don't have stab.h, and they also have
+   no use for DBX-format debugging info.  */
+
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+
+/* The original input file name.  */
+static const char *base_input_file;
+
+/* Current working directory.  */
+
+static const char *cwd;
+
+#ifdef DEBUG_SYMS_TEXT
+#define FORCE_TEXT function_section (current_function_decl);
+#else
+#define FORCE_TEXT
+#endif
+
+#include "gstab.h"
+
+#define STAB_CODE_TYPE enum __stab_debug_code
+
+/* 1 if PARM is passed to this function in memory.  */
+
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+
+/* A C expression for the integer offset value of an automatic variable
+   (N_LSYM) having address X (an RTX).  */
+#ifndef DEBUGGER_AUTO_OFFSET
+#define DEBUGGER_AUTO_OFFSET(X) \
+  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#endif
+
+/* A C expression for the integer offset value of an argument (N_PSYM)
+   having address X (an RTX).  The nominal offset is OFFSET.  */
+#ifndef DEBUGGER_ARG_OFFSET
+#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
+#endif
+
+/* Stream for writing to assembler file.  */
+
+static FILE *asmfile;
 
 /* These variables are for dbxout_symbol to communicate to
    dbxout_finish_symbol.
@@ -293,6 +299,7 @@ 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_fptype_value                PARAMS ((tree));
 static void dbxout_type_index          PARAMS ((tree));
 #if DBX_CONTIN_LENGTH > 0
 static void dbxout_continue            PARAMS ((void));
@@ -303,16 +310,19 @@ 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 bool print_int_cst_bounds_in_octal_p    PARAMS ((tree));
 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 void dbxout_class_name_qualifiers PARAMS ((tree));
 static int dbxout_symbol_location      PARAMS ((tree, tree, const char *, rtx));
 static void dbxout_symbol_name         PARAMS ((tree, const char *, int));
 static void dbxout_prepare_symbol      PARAMS ((tree));
 static void dbxout_finish_symbol       PARAMS ((tree));
 static void dbxout_block               PARAMS ((tree, int, tree));
 static void dbxout_global_decl         PARAMS ((tree));
+static void dbxout_handle_pch          PARAMS ((unsigned));
 \f
 /* The debug hooks structure.  */
 #if defined (DBX_DEBUGGING_INFO)
@@ -325,7 +335,7 @@ 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 =
+const struct gcc_debug_hooks dbx_debug_hooks =
 {
   dbxout_init,
   dbxout_finish,
@@ -338,8 +348,8 @@ struct gcc_debug_hooks dbx_debug_hooks =
   debug_true_tree,             /* ignore_block */
   dbxout_source_line,          /* source_line */
   dbxout_source_line,          /* begin_prologue: just output line info */
-  debug_nothing_int,           /* end_prologue */
-  debug_nothing_void,          /* end_epilogue */
+  debug_nothing_int_charstar,  /* end_prologue */
+  debug_nothing_int_charstar,  /* end_epilogue */
 #ifdef DBX_FUNCTION_FIRST
   dbxout_begin_function,
 #else
@@ -350,12 +360,13 @@ struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_global_decl,          /* global_decl */
   debug_nothing_tree,          /* deferred_inline_function */
   debug_nothing_tree,          /* outlining_inline_function */
-  debug_nothing_rtx            /* label */
+  debug_nothing_rtx,           /* label */
+  dbxout_handle_pch            /* handle_pch */
 };
 #endif /* DBX_DEBUGGING_INFO  */
 
 #if defined (XCOFF_DEBUGGING_INFO)
-struct gcc_debug_hooks xcoff_debug_hooks =
+const struct gcc_debug_hooks xcoff_debug_hooks =
 {
   dbxout_init,
   dbxout_finish,
@@ -368,7 +379,7 @@ struct gcc_debug_hooks xcoff_debug_hooks =
   debug_true_tree,             /* ignore_block */
   xcoffout_source_line,
   xcoffout_begin_prologue,     /* begin_prologue */
-  debug_nothing_int,           /* end_prologue */
+  debug_nothing_int_charstar,  /* end_prologue */
   xcoffout_end_epilogue,
   debug_nothing_tree,          /* begin_function */
   xcoffout_end_function,
@@ -376,7 +387,8 @@ struct gcc_debug_hooks xcoff_debug_hooks =
   dbxout_global_decl,          /* global_decl */
   debug_nothing_tree,          /* deferred_inline_function */
   debug_nothing_tree,          /* outlining_inline_function */
-  debug_nothing_rtx            /* label */
+  debug_nothing_rtx,           /* label */
+  dbxout_handle_pch            /* handle_pch */
 };
 #endif /* XCOFF_DEBUGGING_INFO  */
 \f
@@ -384,22 +396,25 @@ struct gcc_debug_hooks xcoff_debug_hooks =
 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);
+  (*targetm.asm_out.internal_label) (asmfile, "Lscope", scope_labelno);
   scope_labelno++;
 
   /* By convention, GCC will mark the end of a function with an N_FUN
      symbol and an empty string.  */
+#ifdef DBX_OUTPUT_NFUN
+  DBX_OUTPUT_NFUN (asmfile, lscope_label_name, current_function_decl);
+#else
   fprintf (asmfile, "%s\"\",%d,0,0,", ASM_STABS_OP, N_FUN);
   assemble_name (asmfile, lscope_label_name);
   putc ('-', asmfile);
   assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
   fprintf (asmfile, "\n");
+#endif
 }
 #endif /* DBX_DEBUGGING_INFO */
 
@@ -411,12 +426,12 @@ dbxout_init (input_file_name)
      const char *input_file_name;
 {
   char ltext_label_name[100];
-  tree syms = getdecls ();
+  tree syms = (*lang_hooks.decls.getdecls) ();
 
   asmfile = asm_out_file;
 
   typevec_len = 100;
-  typevec = (struct typeinfo *) xcalloc (typevec_len, sizeof typevec[0]);
+  typevec = (struct typeinfo *) ggc_calloc (typevec_len, sizeof typevec[0]);
 
   /* Convert Ltext into the appropriate format for local labels in case
      the system doesn't insert underscores in front of user generated
@@ -424,10 +439,7 @@ dbxout_init (input_file_name)
   ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
 
   /* Put the current working directory in an N_SO symbol.  */
-#ifndef DBX_WORKING_DIRECTORY /* Only some versions of DBX want this,
-                                but GDB always does.  */
   if (use_gnu_debug_info_extensions)
-#endif
     {
       if (!cwd && (cwd = getpwd ()) && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
        cwd = concat (cwd, FILE_NAME_JOINER, NULL);
@@ -438,14 +450,14 @@ dbxout_init (input_file_name)
 #else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
          fprintf (asmfile, "%s", ASM_STABS_OP);
          output_quoted_string (asmfile, cwd);
-         fprintf (asmfile, ",%d,0,0,%s\n", N_SO, &ltext_label_name[1]);
+         fprintf (asmfile, ",%d,0,0,", N_SO);
+         assemble_name (asmfile, ltext_label_name);
+         fputc ('\n', asmfile);
 #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
        }
     }
 
 #ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
-  /* This should NOT be DBX_OUTPUT_SOURCE_FILENAME. That
-     would give us an N_SOL, and we want an N_SO.  */
   DBX_OUTPUT_MAIN_SOURCE_FILENAME (asmfile, input_file_name);
 #else /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
   /* We include outputting `Ltext:' here,
@@ -453,10 +465,11 @@ dbxout_init (input_file_name)
   /* Used to put `Ltext:' before the reference, but that loses on sun 4.  */
   fprintf (asmfile, "%s", ASM_STABS_OP);
   output_quoted_string (asmfile, input_file_name);
-  fprintf (asmfile, ",%d,0,0,%s\n", 
-          N_SO, &ltext_label_name[1]);
+  fprintf (asmfile, ",%d,0,0,", N_SO);
+  assemble_name (asmfile, ltext_label_name);
+  fputc ('\n', asmfile);
   text_section ();
-  ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", 0);
+  (*targetm.asm_out.internal_label) (asmfile, "Ltext", 0);
 #endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
 
 #ifdef DBX_OUTPUT_GCC_MARKER
@@ -467,12 +480,12 @@ dbxout_init (input_file_name)
           ASM_STABS_OP, STABS_GCC_MARKER, N_OPT);
 #endif
 
-  lastfile = input_file_name;
+  base_input_file = lastfile = input_file_name;
 
   next_type_number = 1;
 
 #ifdef DBX_USE_BINCL
-  current_file = (struct dbx_file *) xmalloc (sizeof *current_file);
+  current_file = (struct dbx_file *) ggc_alloc (sizeof *current_file);
   current_file->next = NULL;
   current_file->file_number = 0;
   current_file->next_type_number = 1;
@@ -529,7 +542,7 @@ dbxout_start_source_file (line, filename)
      const char *filename ATTRIBUTE_UNUSED;
 {
 #ifdef DBX_USE_BINCL
-  struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
+  struct dbx_file *n = (struct dbx_file *) ggc_alloc (sizeof *n);
 
   n->next = current_file;
   n->file_number = next_file_number++;
@@ -548,15 +561,36 @@ 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;
+  current_file = current_file->next;
 #endif
 }
 
+/* Handle a few odd cases that occur when trying to make PCH files work.  */
+
+static void
+dbxout_handle_pch (unsigned at_end)
+{
+  if (! at_end)
+    {
+      /* When using the PCH, this file will be included, so we need to output
+        a BINCL.  */
+      dbxout_start_source_file (0, lastfile);
+
+      /* The base file when using the PCH won't be the same as
+        the base file when it's being generated.  */
+      lastfile = NULL;
+    }
+  else
+    {
+      /* ... and an EINCL. */
+      dbxout_end_source_file (0);
+
+      /* Deal with cases where 'lastfile' was never actually changed.  */
+      lastfile_is_base = lastfile == NULL;
+    }
+}
+
 #if defined (DBX_DEBUGGING_INFO)
 /* Output debugging info to FILE to switch to sourcefile FILENAME.  */
 
@@ -565,26 +599,30 @@ dbxout_source_file (file, filename)
      FILE *file;
      const char *filename;
 {
-  char ltext_label_name[100];
+  if (lastfile == 0 && lastfile_is_base)
+    {
+      lastfile = base_input_file;
+      lastfile_is_base = 0;
+    }
 
   if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
     {
-#ifdef DBX_OUTPUT_SOURCE_FILENAME
-      DBX_OUTPUT_SOURCE_FILENAME (file, filename);
-#else
+      char ltext_label_name[100];
+
       ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext",
                                   source_label_number);
       fprintf (file, "%s", ASM_STABS_OP);
       output_quoted_string (file, filename);
-      fprintf (file, ",%d,0,0,%s\n", N_SOL, &ltext_label_name[1]);
+      fprintf (asmfile, ",%d,0,0,", N_SOL);
+      assemble_name (asmfile, ltext_label_name);
+      fputc ('\n', asmfile);
       if (current_function_decl != NULL_TREE
          && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
        ; /* Don't change section amid function.  */
       else
        text_section ();
-      ASM_OUTPUT_INTERNAL_LABEL (file, "Ltext", source_label_number);
+      (*targetm.asm_out.internal_label) (file, "Ltext", source_label_number);
       source_label_number++;
-#endif
       lastfile = filename;
     }
 }
@@ -613,7 +651,7 @@ dbxout_begin_block (line, n)
      unsigned int line ATTRIBUTE_UNUSED;
      unsigned int n;
 {
-  ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBB", n);
+  (*targetm.asm_out.internal_label) (asmfile, "LBB", n);
 }
 
 /* Describe the end line-number of an internal block within a function.  */
@@ -623,7 +661,7 @@ dbxout_end_block (line, n)
      unsigned int line ATTRIBUTE_UNUSED;
      unsigned int n;
 {
-  ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBE", n);
+  (*targetm.asm_out.internal_label) (asmfile, "LBE", n);
 }
 
 /* Output dbx data for a function definition.
@@ -663,7 +701,7 @@ dbxout_global_decl (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
@@ -678,6 +716,61 @@ dbxout_finish (filename)
 #endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */
 }
 
+/* Output floating point type values used by the 'R' stab letter.
+   These numbers come from include/aout/stab_gnu.h in binutils/gdb.
+
+   There are only 3 real/complex types defined, and we need 7/6.
+   We use NF_SINGLE as a generic float type, and NF_COMPLEX as a generic
+   complex type.  Since we have the type size anyways, we don't really need
+   to distinguish between different FP types, we only need to distinguish
+   between float and complex.  This works fine with gdb.
+
+   We only use this for complex types, to avoid breaking backwards
+   compatibility for real types.  complex types aren't in ISO C90, so it is
+   OK if old debuggers don't understand the debug info we emit for them.  */
+
+/* ??? These are supposed to be IEEE types, but we don't check for that.
+   We could perhaps add additional numbers for non-IEEE types if we need
+   them.  */
+
+static void
+dbxout_fptype_value (type)
+     tree type;
+{
+  char value = '0';
+  enum machine_mode mode = TYPE_MODE (type);
+
+  if (TREE_CODE (type) == REAL_TYPE)
+    {
+      if (mode == SFmode)
+       value = '1';
+      else if (mode == DFmode)
+       value = '2';
+      else if (mode == TFmode || mode == XFmode)
+       value = '6';
+      else
+       /* Use NF_SINGLE as a generic real type for other sizes.  */
+       value = '1';
+    }
+  else if (TREE_CODE (type) == COMPLEX_TYPE)
+    {
+      if (mode == SCmode)
+       value = '3';
+      else if (mode == DCmode)
+       value = '4';
+      else if (mode == TCmode || mode == XCmode)
+       value = '5';
+      else
+       /* Use NF_COMPLEX as a generic complex type for other sizes.  */
+       value = '3';
+    }
+  else
+    abort ();
+
+  putc (value, asmfile);
+  CHARS (1);
+}
+
 /* Output the index of a type.  */
 
 static void
@@ -953,7 +1046,7 @@ dbxout_type_methods (type)
        }
       if (!need_prefix)
        {
-          putc (';', asmfile);
+         putc (';', asmfile);
          CHARS (1);
        }
     }
@@ -997,7 +1090,10 @@ dbxout_range_type (type)
     {
       putc (';', asmfile);
       CHARS (1);
-      print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
+      if (print_int_cst_bounds_in_octal_p (type))
+        print_int_cst_octal (TYPE_MIN_VALUE (type));
+      else
+        print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
     }
   else
     {
@@ -1010,7 +1106,10 @@ dbxout_range_type (type)
     {
       putc (';', asmfile);
       CHARS (1);
-      print_wide_int (tree_low_cst (TYPE_MAX_VALUE (type), 0));
+      if (print_int_cst_bounds_in_octal_p (type))
+        print_int_cst_octal (TYPE_MAX_VALUE (type));
+      else
+        print_wide_int (tree_low_cst (TYPE_MAX_VALUE (type), 0));
       putc (';', asmfile);
       CHARS (1);
     }
@@ -1037,10 +1136,13 @@ dbxout_type (type, full)
      int full;
 {
   tree tem;
+  tree main_variant;
   static int anonymous_type_number = 0;
 
   if (TREE_CODE (type) == VECTOR_TYPE)
-    type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+    /* The frontend feeds us a representation for the vector as a struct
+       containing an array.  Pull out the array type.  */
+    type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
 
   /* If there was an input error and we don't really have a type,
      avoid crashing and write something that is at least valid
@@ -1049,24 +1151,24 @@ dbxout_type (type, full)
     type = integer_type_node;
   else
     {
-      /* Try to find the "main variant" with the same name but not const
-        or volatile.  (Since stabs does not distinguish const and volatile,
-        there is no need to make them separate types.  But types with
-        different names are usefully distinguished.) */
-        
-      for (tem = TYPE_MAIN_VARIANT (type); tem; tem = TYPE_NEXT_VARIANT (tem))
-       if (!TYPE_READONLY (tem) && !TYPE_VOLATILE (tem)
-           && TYPE_NAME (tem) == TYPE_NAME (type))
-         {
-           type = tem;
-           break;
-         }
       if (TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
          && TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
        full = 0;
     }
 
+  /* Try to find the "main variant" with the same name.  */
+  if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+    main_variant = TREE_TYPE (TYPE_NAME (type));
+  else
+    main_variant = TYPE_MAIN_VARIANT (type);
+
+  /* If we are not using extensions, stabs does not distinguish const and
+     volatile, so there is no need to make them separate types.  */
+  if (!use_gnu_debug_info_extensions)
+    type = main_variant;
+
   if (TYPE_SYMTAB_ADDRESS (type) == 0)
     {
       /* Type has no dbx number assigned.  Assign next available number.  */
@@ -1077,8 +1179,9 @@ dbxout_type (type, full)
       if (next_type_number == typevec_len)
        {
          typevec
-           = (struct typeinfo *) xrealloc (typevec,
-                                           typevec_len * 2 * sizeof typevec[0]);
+           = (struct typeinfo *) ggc_realloc (typevec,
+                                              (typevec_len * 2 
+                                               * sizeof typevec[0]));
          memset ((char *) (typevec + typevec_len), 0,
                 typevec_len * sizeof typevec[0]);
          typevec_len *= 2;
@@ -1156,12 +1259,30 @@ dbxout_type (type, full)
 
   typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED;
 
-  if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-      && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
-    { 
+  /* If this type is a variant of some other, hand off.  Types with
+     different names are usefully distinguished.  We only distinguish
+     cv-qualified types if we're using extensions.  */
+  if (TYPE_READONLY (type) > TYPE_READONLY (main_variant))
+    {
+      putc ('k', asmfile);
+      CHARS (1);
+      dbxout_type (build_type_variant (type, 0, TYPE_VOLATILE (type)), 0);
+      return;
+    }
+  else if (TYPE_VOLATILE (type) > TYPE_VOLATILE (main_variant))
+    {
+      putc ('B', asmfile);
+      CHARS (1);
+      dbxout_type (build_type_variant (type, TYPE_READONLY (type), 0), 0);
+      return;
+    }
+  else if (main_variant != TYPE_MAIN_VARIANT (type))
+    {
+      /* '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))
     {
@@ -1194,10 +1315,23 @@ dbxout_type (type, full)
         write it as a subtype.  */
       else if (TREE_TYPE (type) != 0
               && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
-       dbxout_range_type (type);
+       {
+         /* If the size is non-standard, say what it is if we can use
+            GDB extensions.  */
+
+         if (use_gnu_debug_info_extensions
+             && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
+           {
+             have_used_extensions = 1;
+             fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
+             CHARS (5);
+           }
+
+         dbxout_range_type (type);
+       }
 
       else
-       {
+       {
          /* If the size is non-standard, say what it is if we can use
             GDB extensions.  */
 
@@ -1209,34 +1343,21 @@ dbxout_type (type, full)
              CHARS (5);
            }
 
-         /* If we can use GDB extensions and the size is wider than a
-            long (the size used by GDB to read them) or we may have
-            trouble writing the bounds the usual way, write them in
-            octal.  Note the test is for the *target's* size of "long",
-            not that of the host.  The host test is just to make sure we
-            can write it out in case the host wide int is narrower than the
-            target "long".  */
-
-         /* For unsigned types, we use octal if they are the same size or
-            larger.  This is because we print the bounds as signed decimal,
-            and hence they can't span same size unsigned types.  */
-
-         if (use_gnu_debug_info_extensions
-             && TYPE_MIN_VALUE (type) != 0
-             && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-             && TYPE_MAX_VALUE (type) != 0
-             && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
-             && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
-                 || ((TYPE_PRECISION (type)
-                      == TYPE_PRECISION (integer_type_node))
-                     && TREE_UNSIGNED (type))
-                 || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
-                 || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
-                     && TREE_UNSIGNED (type))))
+         if (print_int_cst_bounds_in_octal_p (type))
            {
              fprintf (asmfile, "r");
              CHARS (1);
-             dbxout_type_index (type);
+
+              /* If this type derives from another type, output type index of
+                parent type. This is particularly important when parent type
+                is an enumerated type, because not generating the parent type
+                index would transform the definition of this enumerated type
+                into a plain unsigned type.  */
+              if (TREE_TYPE (type) != 0)
+                dbxout_type_index (TREE_TYPE (type));
+              else
+                dbxout_type_index (type);
+
              fprintf (asmfile, ";");
              CHARS (1);
              print_int_cst_octal (TYPE_MIN_VALUE (type));
@@ -1250,7 +1371,7 @@ dbxout_type (type, full)
          else
            /* Output other integer types as subranges of `int'.  */
            dbxout_range_type (type);
-       }
+       }
 
       break;
 
@@ -1317,9 +1438,9 @@ dbxout_type (type, full)
 
       if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
        {
-         fprintf (asmfile, "r");
+         putc ('R', asmfile);
          CHARS (1);
-         dbxout_type_index (type);
+         dbxout_fptype_value (type);
          putc (';', asmfile);
          CHARS (1);
          print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
@@ -1483,16 +1604,27 @@ dbxout_type (type, full)
          }
        for (i = 0; i < n_baseclasses; i++)
          {
-           tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
-
+           tree binfo = TYPE_BINFO (type);
+           tree child = BINFO_BASETYPE (binfo, i);
+           tree access = (BINFO_BASEACCESSES (binfo)
+                          ? BINFO_BASEACCESS (binfo, i) : access_public_node);
+           
            if (use_gnu_debug_info_extensions)
              {
                have_used_extensions = 1;
                putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
-               putc (TREE_VIA_PUBLIC (child) ? '2' : '0', asmfile);
+               putc (access == access_public_node ? '2' : '0', asmfile);
                CHARS (2);
-               print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
-                               * BITS_PER_UNIT);
+               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);
@@ -1579,9 +1711,6 @@ dbxout_type (type, full)
          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))
        {
@@ -1611,7 +1740,6 @@ dbxout_type (type, full)
 
       putc (';', asmfile);
       CHARS (1);
-#endif
       break;
 
     case POINTER_TYPE:
@@ -1676,6 +1804,40 @@ dbxout_type (type, full)
     }
 }
 
+/* Return non-zero if the given type represents an integer whose bounds
+   should be printed in octal format.  */
+
+static bool
+print_int_cst_bounds_in_octal_p (type)
+     tree type;
+{
+  /* If we can use GDB extensions and the size is wider than a long
+     (the size used by GDB to read them) or we may have trouble writing
+     the bounds the usual way, write them in octal.  Note the test is for
+     the *target's* size of "long", not that of the host.  The host test
+     is just to make sure we can write it out in case the host wide int
+     is narrower than the target "long".
+  
+     For unsigned types, we use octal if they are the same size or larger.
+     This is because we print the bounds as signed decimal, and hence they
+     can't span same size unsigned types.  */
+
+  if (use_gnu_debug_info_extensions
+      && TYPE_MIN_VALUE (type) != 0
+      && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
+      && TYPE_MAX_VALUE (type) != 0
+      && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
+      && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
+         || ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+             && TREE_UNSIGNED (type))
+         || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
+         || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
+             && TREE_UNSIGNED (type))))
+    return TRUE;
+  else
+    return FALSE;
+}
+
 /* Print the value of integer constant C, in octal,
    handling double precision.  */
 
@@ -1756,7 +1918,7 @@ print_wide_int (c)
 
   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.  */
@@ -1782,6 +1944,33 @@ dbxout_type_name (type)
   fprintf (asmfile, "%s", IDENTIFIER_POINTER (t));
   CHARS (IDENTIFIER_LENGTH (t));
 }
+
+/* Output leading leading struct or class names needed for qualifying
+   type whose scope is limited to a struct or class.  */
+
+static void
+dbxout_class_name_qualifiers (decl)
+     tree decl;
+{
+  tree context = decl_type_context (decl);
+
+  if (context != NULL_TREE 
+      && TREE_CODE(context) == RECORD_TYPE
+      && TYPE_NAME (context) != 0 
+      && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
+          || (DECL_NAME (TYPE_NAME (context)) != 0)))
+    {
+      tree name = TYPE_NAME (context);
+
+      if (TREE_CODE (name) == TYPE_DECL)
+       {
+         dbxout_class_name_qualifiers (name);
+         name = DECL_NAME (name);
+       }
+      fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
+      CHARS (IDENTIFIER_LENGTH (name) + 2);
+    }
+}
 \f
 /* Output a .stabs for the symbol defined by DECL,
    which must be a ..._DECL node in the normal namespace.
@@ -1902,7 +2091,7 @@ dbxout_symbol (decl, local)
                && !TREE_ASM_WRITTEN (TYPE_NAME (type))
                /* Distinguish the implicit typedefs of C++
                   from explicit ones that might be found in C.  */
-                && DECL_ARTIFICIAL (decl)
+               && DECL_ARTIFICIAL (decl)
                /* Do not generate a tag for records of variable size,
                   since this type can not be properly described in the
                   DBX format, and it confuses some tools such as objdump.  */
@@ -1923,9 +2112,17 @@ dbxout_symbol (decl, local)
                dbxout_finish_symbol (NULL_TREE);
              }
 
+           /* Output .stabs (or whatever) and leading double quote.  */
+           fprintf (asmfile, "%s\"", ASM_STABS_OP);
+
+           if (use_gnu_debug_info_extensions)
+             {
+               /* Output leading class/struct qualifiers.  */
+               dbxout_class_name_qualifiers (decl);
+             }
+
            /* Output typedef name.  */
-           fprintf (asmfile, "%s\"%s:", ASM_STABS_OP,
-                    IDENTIFIER_POINTER (DECL_NAME (decl)));
+           fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (decl)));
 
            /* Short cut way to output a tag also.  */
            if ((TREE_CODE (type) == RECORD_TYPE
@@ -1934,7 +2131,7 @@ dbxout_symbol (decl, local)
                && TYPE_NAME (type) == decl
                /* Distinguish the implicit typedefs of C++
                   from explicit ones that might be found in C.  */
-                && DECL_ARTIFICIAL (decl))
+               && DECL_ARTIFICIAL (decl))
              {
                if (use_gnu_debug_info_extensions && have_used_extensions)
                  {
@@ -2040,14 +2237,9 @@ dbxout_symbol (decl, local)
                  || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
                {
                  HOST_WIDE_INT ival = tree_low_cst (DECL_INITIAL (decl), 0);
-#ifdef DBX_OUTPUT_CONSTANT_SYMBOL
-                 DBX_OUTPUT_CONSTANT_SYMBOL (asmfile, name, ival);
-#else
-                 fprintf (asmfile, "%s\"%s:c=i", ASM_STABS_OP, name);
-
-                 fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, ival);
-                 fprintf (asmfile, "\",0x%x,0,0,0\n", N_LSYM);
-#endif
+                 fprintf (asmfile, "%s\"%s:c=i" HOST_WIDE_INT_PRINT_DEC
+                          "\",0x%x,0,0,0\n",
+                          ASM_STABS_OP, name, ival, N_LSYM);
                  return 1;
                }
              else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE)
@@ -2067,7 +2259,7 @@ dbxout_symbol (decl, local)
 
       result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
       break;
-      
+
     default:
       break;
     }
@@ -2091,7 +2283,7 @@ 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 its rtl
      is not identically the rtl that was used in this
      particular compilation.  */
@@ -2106,7 +2298,7 @@ dbxout_symbol_location (decl, type, suffix, home)
          if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
            return 0;
        }
-      home = alter_subreg (home);
+      home = alter_subreg (&home);
     }
   if (GET_CODE (home) == REG)
     {
@@ -2147,7 +2339,7 @@ dbxout_symbol_location (decl, type, suffix, home)
             we rely on the fact that error_mark_node initializers always
             end up in bss for C++ and never end up in bss for C.  */
          if (DECL_INITIAL (decl) == 0
-             || (!strcmp (lang_identify (), "cplusplus")
+             || (!strcmp (lang_hooks.name, "GNU C++")
                  && DECL_INITIAL (decl) == error_mark_node))
            current_sym_code = N_LCSYM;
          else if (DECL_IN_TEXT_SECTION (decl))
@@ -2156,6 +2348,21 @@ dbxout_symbol_location (decl, type, suffix, home)
            current_sym_code = DBX_STATIC_CONST_VAR_CODE;
          else
            {
+             /* Some ports can transform a symbol ref into a label ref,
+                because the symbol ref is too far away and has to be
+                dumped into a constant pool.  Alternatively, the symbol
+                in the constant pool might be referenced by a different
+                symbol.  */
+             if (GET_CODE (current_sym_addr) == SYMBOL_REF
+                 && CONSTANT_POOL_ADDRESS_P (current_sym_addr))
+               {
+                 rtx tmp = get_pool_constant (current_sym_addr);
+
+                 if (GET_CODE (tmp) == SYMBOL_REF
+                     || GET_CODE (tmp) == LABEL_REF)
+                   current_sym_addr = tmp;
+               }
+
              /* Ultrix `as' seems to need this.  */
 #ifdef DBX_STATIC_STAB_DATA_SECTION
              data_section ();
@@ -2191,6 +2398,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
@@ -2358,7 +2567,7 @@ dbxout_finish_symbol (sym)
 #endif
 }
 
-/* Output definitions of all the decls in a chain. Return non-zero if
+/* Output definitions of all the decls in a chain. Return nonzero if
    anything was output */
 
 int
@@ -2442,7 +2651,7 @@ dbxout_parms (parms)
              }
 
            /* It is quite tempting to use:
-              
+
                   dbxout_type (TREE_TYPE (parms), 0);
 
               as the next statement, rather than using DECL_ARG_TYPE(), so
@@ -2455,7 +2664,7 @@ dbxout_parms (parms)
               double on the stack, but if we emit a stab saying the type is a
               float, then gdb will only read in a single value, and this will
               produce an erroneous value.  */
-           dbxout_type (DECL_ARG_TYPE (parms), 0);
+           dbxout_type (DECL_ARG_TYPE (parms), 0);
            current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
            dbxout_finish_symbol (parms);
          }
@@ -2573,15 +2782,20 @@ dbxout_parms (parms)
            const char *const decl_name = (DECL_NAME (parms)
                                     ? IDENTIFIER_POINTER (DECL_NAME (parms))
                                     : "(anon)");
-           if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
-              current_sym_value = 0;
+           if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
+             current_sym_value = 0;
            else
              current_sym_value
                = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
            current_sym_addr = 0;
-             
+           current_sym_code = N_PSYM;
+
            FORCE_TEXT;
            fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
+
+           current_sym_value
+             = DEBUGGER_ARG_OFFSET (current_sym_value,
+                                    XEXP (XEXP (DECL_RTL (parms), 0), 0));
            dbxout_type (TREE_TYPE (parms), 0);
            dbxout_finish_symbol (parms);
          }
@@ -2613,7 +2827,7 @@ dbxout_parms (parms)
                && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
                && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
              {
-               current_sym_value += 
+               current_sym_value +=
                    GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
                    - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)));
              }
@@ -2723,7 +2937,7 @@ dbxout_block (block, depth, args)
   int blocknum = -1;
 
 #if DBX_BLOCKS_FUNCTION_RELATIVE
-  const char *begin_label; 
+  const char *begin_label;
   if (current_function_func_begin_label != NULL_TREE)
     begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
   else
@@ -2737,9 +2951,6 @@ dbxout_block (block, depth, args)
        {
          int did_output;
 
-#ifdef DBX_LBRAC_FIRST
-         did_output = 1;
-#else
          /* In dbx format, the syms of a block come before the N_LBRAC.
             If nothing is output, we don't need the N_LBRAC, either.  */
          did_output = 0;
@@ -2747,7 +2958,6 @@ dbxout_block (block, depth, args)
            did_output = dbxout_syms (BLOCK_VARS (block));
          if (args)
            dbxout_reg_parms (args);
-#endif
 
          /* Now output an N_LBRAC symbol to represent the beginning of
             the block.  Use the block's tree-walk order to generate
@@ -2765,14 +2975,10 @@ dbxout_block (block, depth, args)
                  tree decl = BLOCK_VARS (block);
                  while (decl)
                    {
-#ifdef DBX_OUTPUT_CATCH
-                     DBX_OUTPUT_CATCH (asmfile, decl, buf);
-#else
                      fprintf (asmfile, "%s\"%s:C1\",%d,0,0,", ASM_STABS_OP,
                               IDENTIFIER_POINTER (DECL_NAME (decl)), N_CATCH);
                      assemble_name (asmfile, buf);
                      fprintf (asmfile, "\n");
-#endif
                      decl = TREE_CHAIN (decl);
                    }
                }
@@ -2790,15 +2996,6 @@ dbxout_block (block, depth, args)
 #endif
            }
 
-#ifdef DBX_LBRAC_FIRST
-         /* On some weird machines, the syms of a block
-            come after the N_LBRAC.  */
-         if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
-           dbxout_syms (BLOCK_VARS (block));
-         if (args)
-           dbxout_reg_parms (args);
-#endif
-
          /* Output the subblocks.  */
          dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
 
@@ -2841,3 +3038,5 @@ dbxout_begin_function (decl)
 #endif /* DBX_DEBUGGING_INFO */
 
 #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+#include "gt-dbxout.h"