OSDN Git Service

2004-08-17 Paul Brook <paul@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / dbxout.c
index e4c7978..f6948a0 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, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -146,6 +146,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define STABS_GCC_MARKER "gcc2_compiled."
 #endif
 
+#ifndef NO_DBX_FUNCTION_END
+#define NO_DBX_FUNCTION_END 0
+#endif
+
 enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
 
 /* Structure recording information about a C data type.
@@ -179,25 +183,40 @@ static GTY(()) int typevec_len;
 
 static GTY(()) int next_type_number;
 
+/* The C front end may call dbxout_symbol before dbxout_init runs.
+   We save all such decls in this list and output them when we get
+   to dbxout_init.  */
+
+static GTY(()) tree preinit_symbols;
+
 enum binclstatus {BINCL_NOT_REQUIRED, BINCL_PENDING, BINCL_PROCESSED};
 
 /* When using N_BINCL in dbx output, each type number is actually a
    pair of the file number and the type number within the file.
    This is a stack of input files.  */
 
-struct dbx_file GTY(())
+struct dbx_file
 {
   struct dbx_file *next;
   int file_number;
   int next_type_number;
-  enum binclstatus bincl_status;      /* Keep track of lazy bincl.  */
-  const char *pending_bincl_name;     /* Name of bincl.  */
-  struct dbx_file *prev;              /* Chain to traverse all pending bincls.  */
+  enum binclstatus bincl_status;  /* Keep track of lazy bincl.  */
+  const char *pending_bincl_name; /* Name of bincl.  */
+  struct dbx_file *prev;          /* Chain to traverse all pending bincls.  */
 };
 
-/* This is the top of the stack.  */
-
-static GTY(()) struct dbx_file *current_file;
+/* This is the top of the stack.  
+   
+   This is not saved for PCH, because restoring a PCH should not change it.
+   next_file_number does have to be saved, because the PCH may use some
+   file numbers; however, just before restoring a PCH, next_file_number
+   should always be 0 because we should not have needed any file numbers
+   yet.  */
+
+#if (defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)) \
+    && defined (DBX_USE_BINCL)
+static struct dbx_file *current_file;
+#endif
 
 /* This is the next file number to use.  */
 
@@ -261,7 +280,7 @@ static const char *cwd;
 /* 1 if PARM is passed to this function in memory.  */
 
 #define PARM_PASSED_IN_MEMORY(PARM) \
- (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+ (MEM_P (DECL_INCOMING_RTL (PARM)))
 
 /* A C expression for the integer offset value of an automatic variable
    (N_LSYM) having address X (an RTX).  */
@@ -328,7 +347,6 @@ static void dbxout_finish (const char *);
 static void dbxout_start_source_file (unsigned, const char *);
 static void dbxout_end_source_file (unsigned);
 static void dbxout_typedefs (tree);
-static void dbxout_fptype_value (tree);
 static void dbxout_type_index (tree);
 #if DBX_CONTIN_LENGTH > 0
 static void dbxout_continue (void);
@@ -351,12 +369,14 @@ static void dbxout_prepare_symbol (tree);
 static void dbxout_finish_symbol (tree);
 static void dbxout_block (tree, int, tree);
 static void dbxout_global_decl (tree);
+static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 \f
 /* The debug hooks structure.  */
 #if defined (DBX_DEBUGGING_INFO)
 
 static void dbxout_source_line (unsigned int, const char *);
+static void dbxout_begin_prologue (unsigned int, const char *);
 static void dbxout_source_file (FILE *, const char *);
 static void dbxout_function_end (void);
 static void dbxout_begin_function (tree);
@@ -374,23 +394,26 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_end_source_file,
   dbxout_begin_block,
   dbxout_end_block,
-  debug_true_tree,             /* ignore_block */
-  dbxout_source_line,          /* source_line */
-  dbxout_source_line,          /* begin_prologue: just output line info */
-  debug_nothing_int_charstar,  /* end_prologue */
-  debug_nothing_int_charstar,  /* end_epilogue */
+  debug_true_tree,                      /* ignore_block */
+  dbxout_source_line,                   /* source_line */
+  dbxout_begin_prologue,                /* begin_prologue */
+  debug_nothing_int_charstar,           /* end_prologue */
+  debug_nothing_int_charstar,           /* end_epilogue */
 #ifdef DBX_FUNCTION_FIRST
   dbxout_begin_function,
 #else
-  debug_nothing_tree,          /* begin_function */
+  debug_nothing_tree,                   /* begin_function */
 #endif
-  debug_nothing_int,           /* end_function */
+  debug_nothing_int,                    /* end_function */
   dbxout_function_decl,
-  dbxout_global_decl,          /* global_decl */
-  debug_nothing_tree,          /* deferred_inline_function */
-  debug_nothing_tree,          /* outlining_inline_function */
-  debug_nothing_rtx,           /* label */
-  dbxout_handle_pch            /* handle_pch */
+  dbxout_global_decl,                   /* global_decl */
+  dbxout_type_decl,                     /* type_decl */
+  debug_nothing_tree_tree,               /* imported_module_or_decl */
+  debug_nothing_tree,                   /* deferred_inline_function */
+  debug_nothing_tree,                   /* outlining_inline_function */
+  debug_nothing_rtx,                    /* label */
+  dbxout_handle_pch,                    /* handle_pch */
+  debug_nothing_rtx                     /* var_location */
 };
 #endif /* DBX_DEBUGGING_INFO  */
 
@@ -405,19 +428,22 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   dbxout_end_source_file,
   xcoffout_begin_block,
   xcoffout_end_block,
-  debug_true_tree,             /* ignore_block */
+  debug_true_tree,                      /* ignore_block */
   xcoffout_source_line,
-  xcoffout_begin_prologue,     /* begin_prologue */
-  debug_nothing_int_charstar,  /* end_prologue */
+  xcoffout_begin_prologue,              /* begin_prologue */
+  debug_nothing_int_charstar,           /* end_prologue */
   xcoffout_end_epilogue,
-  debug_nothing_tree,          /* begin_function */
+  debug_nothing_tree,                   /* begin_function */
   xcoffout_end_function,
-  debug_nothing_tree,          /* function_decl */
-  dbxout_global_decl,          /* global_decl */
-  debug_nothing_tree,          /* deferred_inline_function */
-  debug_nothing_tree,          /* outlining_inline_function */
-  debug_nothing_rtx,           /* label */
-  dbxout_handle_pch            /* handle_pch */
+  debug_nothing_tree,                   /* function_decl */
+  dbxout_global_decl,                   /* global_decl */
+  dbxout_type_decl,                     /* type_decl */
+  debug_nothing_tree_tree,               /* imported_module_or_decl */
+  debug_nothing_tree,                   /* deferred_inline_function */
+  debug_nothing_tree,                   /* outlining_inline_function */
+  debug_nothing_rtx,                    /* label */
+  dbxout_handle_pch,                    /* handle_pch */
+  debug_nothing_rtx                     /* var_location */
 };
 #endif /* XCOFF_DEBUGGING_INFO  */
 \f
@@ -426,13 +452,26 @@ static void
 dbxout_function_end (void)
 {
   char lscope_label_name[100];
+
+  /* The Lscope label must be emitted even if we aren't doing anything
+     else; dbxout_block needs it.  */
+  function_section (current_function_decl);
+  
   /* 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);
-  (*targetm.asm_out.internal_label) (asmfile, "Lscope", scope_labelno);
+  targetm.asm_out.internal_label (asmfile, "Lscope", scope_labelno);
   scope_labelno++;
 
+  /* The N_FUN tag at the end of the function is a GNU extension,
+     which may be undesirable, and is unnecessary if we do not have
+     named sections.  */
+  if (!use_gnu_debug_info_extensions
+      || NO_DBX_FUNCTION_END
+      || !targetm.have_named_sections)
+    return;
+
   /* By convention, GCC will mark the end of a function with an N_FUN
      symbol and an empty string.  */
 #ifdef DBX_OUTPUT_NFUN
@@ -444,6 +483,9 @@ dbxout_function_end (void)
   assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
   fprintf (asmfile, "\n");
 #endif
+
+  if (!flag_debug_only_used_symbols)
+    fprintf (asmfile, "%s%d,0,0\n", ASM_STABD_OP, N_ENSYM);
 }
 #endif /* DBX_DEBUGGING_INFO */
 
@@ -454,7 +496,7 @@ static void
 dbxout_init (const char *input_file_name)
 {
   char ltext_label_name[100];
-  tree syms = (*lang_hooks.decls.getdecls) ();
+  tree syms = lang_hooks.decls.getdecls ();
 
   asmfile = asm_out_file;
 
@@ -498,7 +540,7 @@ dbxout_init (const char *input_file_name)
   assemble_name (asmfile, ltext_label_name);
   fputc ('\n', asmfile);
   text_section ();
-  (*targetm.asm_out.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
@@ -514,7 +556,7 @@ dbxout_init (const char *input_file_name)
   next_type_number = 1;
 
 #ifdef DBX_USE_BINCL
-  current_file = ggc_alloc (sizeof *current_file);
+  current_file = xmalloc (sizeof *current_file);
   current_file->next = NULL;
   current_file->file_number = 0;
   current_file->next_type_number = 1;
@@ -524,39 +566,35 @@ dbxout_init (const char *input_file_name)
   current_file->pending_bincl_name = NULL;
 #endif
 
-  /* Make sure that types `int' and `char' have numbers 1 and 2.
-     Definitions of other integer types will refer to those numbers.
-     (Actually it should no longer matter what their numbers are.
-     Also, if any types with tags have been defined, dbxout_symbol
-     will output them first, so the numbers won't be 1 and 2.  That
-     happens in C++.  So it's a good thing it should no longer matter).  */
-
-#ifdef DBX_OUTPUT_STANDARD_TYPES
-  DBX_OUTPUT_STANDARD_TYPES (syms);
-#endif
-
   /* Get all permanent types that have typedef names, and output them
      all, except for those already output.  Some language front ends
-     put these declarations in the top-level scope; some do not.  */
-  dbxout_typedefs ((*lang_hooks.decls.builtin_type_decls) ());
+     put these declarations in the top-level scope; some do not;
+     the latter are responsible for calling debug_hooks->type_decl from
+     their record_builtin_type function.  */
   dbxout_typedefs (syms);
+
+  if (preinit_symbols)
+    {
+      tree t;
+      for (t = nreverse (preinit_symbols); t; t = TREE_CHAIN (t))
+       dbxout_symbol (TREE_VALUE (t), 0);
+      preinit_symbols = 0;
+    }
 }
 
-/* Output any typedef names for types described by TYPE_DECLs in SYMS,
-   in the reverse order from that which is found in SYMS.  */
+/* Output any typedef names for types described by TYPE_DECLs in SYMS.  */
 
 static void
 dbxout_typedefs (tree syms)
 {
-  if (syms)
+  for (; syms != NULL_TREE; syms = TREE_CHAIN (syms))
     {
-      dbxout_typedefs (TREE_CHAIN (syms));
       if (TREE_CODE (syms) == TYPE_DECL)
        {
          tree type = TREE_TYPE (syms);
          if (TYPE_NAME (type)
              && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-             && COMPLETE_TYPE_P (type)
+             && COMPLETE_OR_VOID_TYPE_P (type)
              && ! TREE_ASM_WRITTEN (TYPE_NAME (type)))
            dbxout_symbol (TYPE_NAME (type), 0);
        }
@@ -628,7 +666,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
                          const char *filename ATTRIBUTE_UNUSED)
 {
 #ifdef DBX_USE_BINCL
-  struct dbx_file *n = ggc_alloc (sizeof *n);
+  struct dbx_file *n = xmalloc (sizeof *n);
 
   n->next = current_file;
   n->next_type_number = 1;
@@ -710,13 +748,29 @@ dbxout_source_file (FILE *file, const char *filename)
          && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
        ; /* Don't change section amid function.  */
       else
-       text_section ();
-      (*targetm.asm_out.internal_label) (file, "Ltext", source_label_number);
+       {
+         if (!in_text_section () && !in_unlikely_text_section ())
+           text_section ();
+       }
+      targetm.asm_out.internal_label (file, "Ltext", source_label_number);
       source_label_number++;
       lastfile = filename;
     }
 }
 
+/* Output N_BNSYM and line number symbol entry.  */
+
+static void
+dbxout_begin_prologue (unsigned int lineno, const char *filename)
+{
+  if (use_gnu_debug_info_extensions
+      && !NO_DBX_FUNCTION_END
+      && !flag_debug_only_used_symbols)
+    fprintf (asmfile, "%s%d,0,0\n", ASM_STABD_OP, N_BNSYM);
+
+  dbxout_source_line (lineno, filename);
+}
+
 /* Output a line number symbol entry for source file FILENAME and line
    number LINENO.  */
 
@@ -739,7 +793,7 @@ static void
 dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
 {
   emit_pending_bincls_if_required ();
-  (*targetm.asm_out.internal_label) (asmfile, "LBB", n);
+  targetm.asm_out.internal_label (asmfile, "LBB", n);
 }
 
 /* Describe the end line-number of an internal block within a function.  */
@@ -748,7 +802,7 @@ static void
 dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
 {
   emit_pending_bincls_if_required ();
-  (*targetm.asm_out.internal_label) (asmfile, "LBE", n);
+  targetm.asm_out.internal_label (asmfile, "LBE", n);
 }
 
 /* Output dbx data for a function definition.
@@ -768,12 +822,7 @@ dbxout_function_decl (tree 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 ();
+  dbxout_function_end ();
 }
 
 #endif /* DBX_DEBUGGING_INFO  */
@@ -794,6 +843,14 @@ dbxout_global_decl (tree decl)
     }
 }
 
+/* This is just a function-type adapter; dbxout_symbol does exactly
+   what we want but returns an int.  */
+static void
+dbxout_type_decl (tree decl, int local)
+{
+  dbxout_symbol (decl, local);
+}
+
 /* 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.  */
@@ -808,60 +865,6 @@ dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
   debug_free_queue ();
 }
 
-/* Output floating point type values used by the 'R' stab letter.
-   These numbers come from include/aout/stab_gnu.h in binutils/gdb.
-
-   There are only 3 real/complex types defined, and we need 7/6.
-   We use NF_SINGLE as a generic float type, and NF_COMPLEX as a generic
-   complex type.  Since we have the type size anyways, we don't really need
-   to distinguish between different FP types, we only need to distinguish
-   between float and complex.  This works fine with gdb.
-
-   We only use this for complex types, to avoid breaking backwards
-   compatibility for real types.  complex types aren't in ISO C90, so it is
-   OK if old debuggers don't understand the debug info we emit for them.  */
-
-/* ??? These are supposed to be IEEE types, but we don't check for that.
-   We could perhaps add additional numbers for non-IEEE types if we need
-   them.  */
-
-static void
-dbxout_fptype_value (tree type)
-{
-  char value = '0';
-  enum machine_mode mode = TYPE_MODE (type);
-
-  if (TREE_CODE (type) == REAL_TYPE)
-    {
-      if (mode == SFmode)
-       value = '1';
-      else if (mode == DFmode)
-       value = '2';
-      else if (mode == TFmode || mode == XFmode)
-       value = '6';
-      else
-       /* Use NF_SINGLE as a generic real type for other sizes.  */
-       value = '1';
-    }
-  else if (TREE_CODE (type) == COMPLEX_TYPE)
-    {
-      if (mode == SCmode)
-       value = '3';
-      else if (mode == DCmode)
-       value = '4';
-      else if (mode == TCmode || mode == XCmode)
-       value = '5';
-      else
-       /* Use NF_COMPLEX as a generic complex type for other sizes.  */
-       value = '3';
-    }
-  else
-    abort ();
-
-  putc (value, asmfile);
-  CHARS (1);
-}
-
 /* Output the index of a type.  */
 
 static void
@@ -912,6 +915,11 @@ dbxout_type_fields (tree type)
      field that we can support.  */
   for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
     {
+      /* If one of the nodes is an error_mark or its type is then
+        return early.  */
+      if (tem == error_mark_node || TREE_TYPE (tem) == error_mark_node)
+       return;
+
       /* Omit here local type decls until we know how to support them.  */
       if (TREE_CODE (tem) == TYPE_DECL
          /* Omit fields whose position or size are variable or too large to
@@ -1407,7 +1415,7 @@ dbxout_type (tree type, int full)
       break;
 
     case INTEGER_TYPE:
-      if (type == char_type_node && ! TREE_UNSIGNED (type))
+      if (type == char_type_node && ! TYPE_UNSIGNED (type))
        {
          /* Output the type `char' as a subrange of itself!
             I don't understand this definition, just copied it
@@ -1515,7 +1523,7 @@ dbxout_type (tree type, int full)
          fprintf (asmfile, "r");
          CHARS (1);
          dbxout_type_index (char_type_node);
-         fprintf (asmfile, ";0;%d;", TREE_UNSIGNED (type) ? 255 : 127);
+         fprintf (asmfile, ";0;%d;", TYPE_UNSIGNED (type) ? 255 : 127);
          CHARS (7);
        }
       break;
@@ -1544,15 +1552,14 @@ dbxout_type (tree type, int full)
       break;
 
     case COMPLEX_TYPE:
-      /* Differs from the REAL_TYPE by its new data type number */
+      /* Differs from the REAL_TYPE by its new data type number.
+        R3 is NF_COMPLEX.  We don't try to use any of the other NF_*
+        codes since gdb doesn't care anyway.  */
 
       if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
        {
-         putc ('R', asmfile);
-         CHARS (1);
-         dbxout_fptype_value (type);
-         putc (';', asmfile);
-         CHARS (1);
+         fputs ("R3;", asmfile);
+         CHARS (3);
          print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
          fputs (";0;", asmfile);
          CHARS (3);
@@ -1651,12 +1658,7 @@ dbxout_type (tree type, int full)
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
       {
-       int i, n_baseclasses = 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));
+       tree binfo = TYPE_BINFO (type);
 
        /* Output a structure type.  We must use the same test here as we
           use in the DBX_NO_XREFS case above.  */
@@ -1703,63 +1705,72 @@ dbxout_type (tree type, int full)
        CHARS (1);
        print_wide_int (int_size_in_bytes (type));
 
-       if (use_gnu_debug_info_extensions)
+       if (binfo)
          {
-           if (n_baseclasses)
-             {
-               have_used_extensions = 1;
-               fprintf (asmfile, "!%d,", n_baseclasses);
-               CHARS (8);
-             }
-         }
-       for (i = 0; i < n_baseclasses; i++)
-         {
-           tree binfo = TYPE_BINFO (type);
-           tree child = BINFO_BASETYPE (binfo, i);
-           tree access = (BINFO_BASEACCESSES (binfo)
-                          ? BINFO_BASEACCESS (binfo, i) : access_public_node);
-
+           int i;
+           tree child;
+           VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo);
+           
            if (use_gnu_debug_info_extensions)
              {
-               have_used_extensions = 1;
-               putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
-               putc (access == access_public_node ? '2' : '0', asmfile);
-               CHARS (2);
-               if (TREE_VIA_VIRTUAL (child)
-                   && strcmp (lang_hooks.name, "GNU C++") == 0)
-                 /* For a virtual base, print the (negative) offset within
-                    the vtable where we must look to find the necessary
-                    adjustment.  */
-                 print_wide_int (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
-                                 * BITS_PER_UNIT);
-               else
-                 print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
-                                 * BITS_PER_UNIT);
-               putc (',', asmfile);
-               CHARS (1);
-               dbxout_type (BINFO_TYPE (child), 0);
-               putc (';', asmfile);
-               CHARS (1);
+               if (BINFO_N_BASE_BINFOS (binfo))
+                 {
+                   have_used_extensions = 1;
+                   fprintf (asmfile, "!%u,", BINFO_N_BASE_BINFOS (binfo));
+                   CHARS (8);
+                 }
              }
-           else
+           for (i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++)
              {
-               /* Print out the base class information with fields
-                  which have the same names at the types they hold.  */
-               dbxout_type_name (BINFO_TYPE (child));
-               putc (':', asmfile);
-               CHARS (1);
-               dbxout_type (BINFO_TYPE (child), full);
-               putc (',', asmfile);
-               CHARS (1);
-               print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
-                               * BITS_PER_UNIT);
-               putc (',', asmfile);
-               CHARS (1);
-               print_wide_int (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)),
-                                             0)
-                               * BITS_PER_UNIT);
-               putc (';', asmfile);
-               CHARS (1);
+               tree access = (accesses ? VEC_index (tree, accesses, i)
+                              : access_public_node);
+
+               if (use_gnu_debug_info_extensions)
+                 {
+                   have_used_extensions = 1;
+                   putc (BINFO_VIRTUAL_P (child) ? '1' : '0', asmfile);
+                   putc (access == access_public_node ? '2' :
+                         (access == access_protected_node ? '1' :'0'),
+                         asmfile);
+                   CHARS (2);
+                   if (BINFO_VIRTUAL_P (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
+                 {
+                   /* Print out the base class information with
+                      fields which have the same names at the types
+                      they hold.  */
+                   dbxout_type_name (BINFO_TYPE (child));
+                   putc (':', asmfile);
+                   CHARS (1);
+                   dbxout_type (BINFO_TYPE (child), full);
+                   putc (',', asmfile);
+                   CHARS (1);
+                   print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
+                                   * BITS_PER_UNIT);
+                   putc (',', asmfile);
+                   CHARS (1);
+                   print_wide_int
+                     (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)), 0)
+                      * BITS_PER_UNIT);
+                   putc (';', asmfile);
+                   CHARS (1);
+                 }
              }
          }
       }
@@ -1936,10 +1947,10 @@ print_int_cst_bounds_in_octal_p (tree type)
       && 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_UNSIGNED (type))
          || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
          || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
-             && TREE_UNSIGNED (type))))
+             && TYPE_UNSIGNED (type))))
     return TRUE;
   else
     return FALSE;
@@ -2091,11 +2102,6 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
   /* "Intercept" dbxout_symbol() calls like we do all debug_hooks.  */
   ++debug_nesting;
 
-  /* Cast avoids warning in old compilers.  */
-  current_sym_code = (STAB_CODE_TYPE) 0;
-  current_sym_value = 0;
-  current_sym_addr = 0;
-
   /* Ignore nameless syms, but don't ignore type tags.  */
 
   if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)
@@ -2106,14 +2112,22 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
      symbol nodees are flagged with TREE_USED.  Ignore any that
      aren't flaged as TREE_USED.  */
 
+  if (flag_debug_only_used_symbols
+      && (!TREE_USED (decl)
+          && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl))))
+    DBXOUT_DECR_NESTING_AND_RETURN (0);
+
+  /* If dbxout_init has not yet run, queue this symbol for later.  */
+  if (!typevec)
+    {
+      preinit_symbols = tree_cons (0, decl, preinit_symbols);
+      DBXOUT_DECR_NESTING_AND_RETURN (0);
+    }
+
   if (flag_debug_only_used_symbols)
     {
       tree t;
 
-      if (!TREE_USED (decl)
-          && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl)))
-        DBXOUT_DECR_NESTING_AND_RETURN (0);
-
       /* We now have a used symbol.  We need to generate the info for
          the symbol's type in addition to the symbol itself.  These
          type symbols are queued to be generated after were done with
@@ -2182,7 +2196,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       context = decl_function_context (decl);
       if (context == current_function_decl)
        break;
-      if (GET_CODE (DECL_RTL (decl)) != MEM
+      if (!MEM_P (DECL_RTL (decl))
          || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
        break;
       FORCE_TEXT;
@@ -2217,6 +2231,20 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
        DBXOUT_DECR_NESTING_AND_RETURN (0);
 
+      /* Don't output typedefs for types with magic type numbers (XCOFF).  */
+#ifdef DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER
+      {
+       int fundamental_type_number =
+         DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER (decl);
+
+       if (fundamental_type_number != 0)
+         {
+           TREE_ASM_WRITTEN (decl) = 1;
+           TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = fundamental_type_number;
+           DBXOUT_DECR_NESTING_AND_RETURN (0);
+         }
+      }
+#endif
       FORCE_TEXT;
       result = 1;
       {
@@ -2396,7 +2424,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
                }
              else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE)
                {
-                 /* don't know how to do this yet.  */
+                 /* Don't know how to do this yet.  */
                }
              break;
            }
@@ -2445,14 +2473,14 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
 
       while (GET_CODE (value) == SUBREG)
        value = SUBREG_REG (value);
-      if (GET_CODE (value) == REG)
+      if (REG_P (value))
        {
          if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
            return 0;
        }
       home = alter_subreg (&home);
     }
-  if (GET_CODE (home) == REG)
+  if (REG_P (home))
     {
       regno = REGNO (home);
       if (regno >= FIRST_PSEUDO_REGISTER)
@@ -2472,7 +2500,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
      no letter at all, and N_LSYM, for auto variable,
      r and N_RSYM for register variable.  */
 
-  if (GET_CODE (home) == MEM
+  if (MEM_P (home)
       && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
     {
       if (TREE_PUBLIC (decl))
@@ -2508,11 +2536,27 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
              if (GET_CODE (current_sym_addr) == SYMBOL_REF
                  && CONSTANT_POOL_ADDRESS_P (current_sym_addr))
                {
-                 rtx tmp = get_pool_constant (current_sym_addr);
+                 bool marked;
+                 rtx tmp = get_pool_constant_mark (current_sym_addr, &marked);
 
-                 if (GET_CODE (tmp) == SYMBOL_REF
-                     || GET_CODE (tmp) == LABEL_REF)
-                   current_sym_addr = tmp;
+                 if (GET_CODE (tmp) == SYMBOL_REF)
+                   {
+                     current_sym_addr = tmp;
+                     if (CONSTANT_POOL_ADDRESS_P (current_sym_addr))
+                       get_pool_constant_mark (current_sym_addr, &marked);
+                     else
+                       marked = true;
+                   }
+                 else if (GET_CODE (tmp) == LABEL_REF)
+                   {
+                     current_sym_addr = tmp;
+                     marked = true;
+                   }
+
+                  /* If all references to the constant pool were optimized
+                     out, we just ignore the symbol.  */
+                 if (!marked)
+                   return 0;
                }
 
              /* Ultrix `as' seems to need this.  */
@@ -2529,9 +2573,9 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
       current_sym_code = N_RSYM;
       current_sym_value = DBX_REGISTER_NUMBER (regno);
     }
-  else if (GET_CODE (home) == MEM
-          && (GET_CODE (XEXP (home, 0)) == MEM
-              || (GET_CODE (XEXP (home, 0)) == REG
+  else if (MEM_P (home)
+          && (MEM_P (XEXP (home, 0))
+              || (REG_P (XEXP (home, 0))
                   && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
                   && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
@@ -2543,10 +2587,9 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
        then it means the object is variable-sized and address through
        that register or stack slot.  DBX has no way to represent this
        so all we can do is output the variable as a pointer.
-       If it's not a parameter, ignore it.
-       (VAR_DECLs like this can be made by integrate.c.)  */
+       If it's not a parameter, ignore it.  */
     {
-      if (GET_CODE (XEXP (home, 0)) == REG)
+      if (REG_P (XEXP (home, 0)))
        {
          letter = 'r';
          current_sym_code = N_RSYM;
@@ -2570,13 +2613,13 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
       type = make_node (POINTER_TYPE);
       TREE_TYPE (type) = TREE_TYPE (decl);
     }
-  else if (GET_CODE (home) == MEM
-          && GET_CODE (XEXP (home, 0)) == REG)
+  else if (MEM_P (home)
+          && REG_P (XEXP (home, 0)))
     {
       current_sym_code = N_LSYM;
       current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
     }
-  else if (GET_CODE (home) == MEM
+  else if (MEM_P (home)
           && GET_CODE (XEXP (home, 0)) == PLUS
           && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
     {
@@ -2585,7 +2628,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
         We want the value of that CONST_INT.  */
       current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
     }
-  else if (GET_CODE (home) == MEM
+  else if (MEM_P (home)
           && GET_CODE (XEXP (home, 0)) == CONST)
     {
       /* Handle an obscure case which can arise when optimizing and
@@ -2622,10 +2665,6 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
       else
        dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 0));
 
-      /* Cast avoids warning in old compilers.  */
-      current_sym_code = (STAB_CODE_TYPE) 0;
-      current_sym_value = 0;
-      current_sym_addr = 0;
       dbxout_prepare_symbol (decl);
 
       if (WORDS_BIG_ENDIAN)
@@ -2665,9 +2704,11 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter)
 {
   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
+  if (DECL_CONTEXT (decl) 
+      && (TYPE_P (DECL_CONTEXT (decl))
+         || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
+    /* One slight hitch: if this is a VAR_DECL which is a class member
+       or a namespace 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));
@@ -2693,6 +2734,14 @@ dbxout_prepare_symbol (tree decl ATTRIBUTE_UNUSED)
 
   dbxout_source_file (asmfile, filename);
 #endif
+
+  /* Initialize variables used to communicate each symbol's debug
+     information to dbxout_finish_symbol with zeroes.  */
+
+  /* Cast avoids warning in old compilers.  */
+  current_sym_code = (STAB_CODE_TYPE) 0;
+  current_sym_value = 0;
+  current_sym_addr = 0;
 }
 
 static void
@@ -2749,7 +2798,10 @@ dbxout_parms (tree parms)
   emit_pending_bincls_if_required ();
 
   for (; parms; parms = TREE_CHAIN (parms))
-    if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+    if (DECL_NAME (parms)
+       && TREE_TYPE (parms) != error_mark_node
+       && DECL_RTL_SET_P (parms)
+       && DECL_INCOMING_RTL (parms))
       {
        dbxout_prepare_symbol (parms);
 
@@ -2817,7 +2869,7 @@ dbxout_parms (tree parms)
            current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
            dbxout_finish_symbol (parms);
          }
-       else if (GET_CODE (DECL_RTL (parms)) == REG)
+       else if (REG_P (DECL_RTL (parms)))
          {
            rtx best_rtl;
            char regparm_letter;
@@ -2867,8 +2919,8 @@ dbxout_parms (tree parms)
            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
+       else if (MEM_P (DECL_RTL (parms))
+                && REG_P (XEXP (DECL_RTL (parms), 0))
                 && 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
@@ -2921,8 +2973,8 @@ dbxout_parms (tree parms)
            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)
+       else if (MEM_P (DECL_RTL (parms))
+                && MEM_P (XEXP (DECL_RTL (parms), 0)))
          {
            /* Parm was passed via invisible reference, with the reference
               living on the stack.  DECL_RTL looks like
@@ -2931,7 +2983,7 @@ dbxout_parms (tree 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)
+           if (REG_P (XEXP (XEXP (DECL_RTL (parms), 0), 0)))
              current_sym_value = 0;
            else
              current_sym_value
@@ -2948,7 +3000,7 @@ dbxout_parms (tree parms)
            dbxout_type (TREE_TYPE (parms), 0);
            dbxout_finish_symbol (parms);
          }
-       else if (GET_CODE (DECL_RTL (parms)) == MEM
+       else if (MEM_P (DECL_RTL (parms))
                 && XEXP (DECL_RTL (parms), 0) != const0_rtx
                 /* ??? A constant address for a parm can happen
                    when the reg it lives in is equiv to a constant in memory.
@@ -2962,7 +3014,7 @@ dbxout_parms (tree parms)
               in which case we want the value of that CONST_INT,
               or (MEM (REG ...)),
               in which case we use a value of zero.  */
-           if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)
+           if (REG_P (XEXP (DECL_RTL (parms), 0)))
              current_sym_value = 0;
            else
                current_sym_value
@@ -3031,7 +3083,7 @@ dbxout_reg_parms (tree parms)
 
        /* Report parms that live in registers during the function
           but were passed in memory.  */
-       if (GET_CODE (DECL_RTL (parms)) == REG
+       if (REG_P (DECL_RTL (parms))
            && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
          dbxout_symbol_location (parms, TREE_TYPE (parms),
                                  0, DECL_RTL (parms));
@@ -3039,7 +3091,7 @@ dbxout_reg_parms (tree parms)
          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
+       else if (MEM_P (DECL_RTL (parms))
                 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
          dbxout_symbol_location (parms, TREE_TYPE (parms),
                                  0, DECL_RTL (parms));
@@ -3062,6 +3114,46 @@ dbxout_args (tree args)
     }
 }
 \f
+/* Subroutine of dbxout_block.  Emit an N_LBRAC stab referencing LABEL.
+   BEGIN_LABEL is the name of the beginning of the function, which may
+   be required.  */
+static void
+dbx_output_lbrac (const char *label,
+                 const char *begin_label ATTRIBUTE_UNUSED)
+{
+#ifdef DBX_OUTPUT_LBRAC
+  DBX_OUTPUT_LBRAC (asmfile, label);
+#else
+  fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_LBRAC);
+  assemble_name (asmfile, label);
+#if DBX_BLOCKS_FUNCTION_RELATIVE
+  putc ('-', asmfile);
+  assemble_name (asmfile, begin_label);
+#endif
+  fprintf (asmfile, "\n");
+#endif
+}
+
+/* Subroutine of dbxout_block.  Emit an N_RBRAC stab referencing LABEL.
+   BEGIN_LABEL is the name of the beginning of the function, which may
+   be required.  */
+static void
+dbx_output_rbrac (const char *label,
+                 const char *begin_label ATTRIBUTE_UNUSED)
+{
+#ifdef DBX_OUTPUT_RBRAC
+  DBX_OUTPUT_RBRAC (asmfile, label);
+#else
+  fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_RBRAC);
+  assemble_name (asmfile, label);
+#if DBX_BLOCKS_FUNCTION_RELATIVE
+  putc ('-', asmfile);
+  assemble_name (asmfile, begin_label);
+#endif
+  fprintf (asmfile, "\n");
+#endif
+}
+
 /* Output everything about a symbol block (a BLOCK node
    that represents a scope level),
    including recursive output of contained blocks.
@@ -3082,15 +3174,11 @@ dbxout_args (tree args)
 static void
 dbxout_block (tree block, int depth, tree args)
 {
-  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)
     {
@@ -3098,6 +3186,7 @@ dbxout_block (tree block, int depth, tree args)
       if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
        {
          int did_output;
+         int blocknum = BLOCK_NUMBER (block);
 
          /* 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.  */
@@ -3111,11 +3200,20 @@ dbxout_block (tree block, int depth, tree 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 && did_output)
+         if (did_output)
            {
              char buf[20];
-             blocknum = BLOCK_NUMBER (block);
-             ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum);
+             const char *scope_start;
+
+             if (depth == 0)
+               /* The outermost block doesn't get LBB labels; use
+                  the function symbol.  */
+               scope_start = begin_label;
+             else
+               {
+                 ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum);
+                 scope_start = buf;
+               }
 
              if (BLOCK_HANDLER_BLOCK (block))
                {
@@ -3125,44 +3223,30 @@ dbxout_block (tree block, int depth, tree args)
                    {
                      fprintf (asmfile, "%s\"%s:C1\",%d,0,0,", ASM_STABS_OP,
                               IDENTIFIER_POINTER (DECL_NAME (decl)), N_CATCH);
-                     assemble_name (asmfile, buf);
+                     assemble_name (asmfile, scope_start);
                      fprintf (asmfile, "\n");
                      decl = TREE_CHAIN (decl);
                    }
                }
-
-#ifdef DBX_OUTPUT_LBRAC
-             DBX_OUTPUT_LBRAC (asmfile, buf);
-#else
-             fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_LBRAC);
-             assemble_name (asmfile, buf);
-#if DBX_BLOCKS_FUNCTION_RELATIVE
-             putc ('-', asmfile);
-             assemble_name (asmfile, begin_label);
-#endif
-             fprintf (asmfile, "\n");
-#endif
+             dbx_output_lbrac (scope_start, begin_label);
            }
 
          /* Output the subblocks.  */
          dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
 
          /* Refer to the marker for the end of the block.  */
-         if (depth > 0 && did_output)
+         if (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);
-             assemble_name (asmfile, buf);
-#if DBX_BLOCKS_FUNCTION_RELATIVE
-             putc ('-', asmfile);
-             assemble_name (asmfile, begin_label);
-#endif
-             fprintf (asmfile, "\n");
-#endif
+             char buf[100];
+             if (depth == 0)
+               /* The outermost block doesn't get LBE labels;
+                  use the "scope" label which will be emitted
+                  by dbxout_function_end.  */
+               ASM_GENERATE_INTERNAL_LABEL (buf, "Lscope", scope_labelno);
+             else
+               ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum);
+
+             dbx_output_rbrac (buf, begin_label);
            }
        }
       block = BLOCK_CHAIN (block);