OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / sdbout.c
index ebc7443..f0075d5 100644 (file)
@@ -1,5 +1,6 @@
 /* Output sdb-format symbol table information from GNU compiler.
-   Copyright (C) 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +16,8 @@ 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.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /*  mike@tredysvr.Tredydev.Unisys.COM says:
 I modified the struct.c example and have a nm of a .o resulting from the
@@ -34,7 +36,7 @@ AT&T C compiler.  From the example below I would conclude the following:
 4. All structure .defs are emitted before the typedefs that refer to them.
 
 5. All top level static and external variable definitions are moved to the
-   end of file with all top level statics occuring first before externs.
+   end of file with all top level statics occurring first before externs.
 
 6. All undefined references are at the end of the file.
 */
@@ -43,25 +45,31 @@ AT&T C compiler.  From the example below I would conclude the following:
 
 #ifdef SDB_DEBUGGING_INFO
 
+#include "system.h"
 #include "tree.h"
 #include "rtl.h"
-#include <stdio.h>
 #include "regs.h"
+#include "defaults.h"
 #include "flags.h"
 #include "insn-config.h"
 #include "reload.h"
+#include "output.h"
+#include "toplev.h"
+#include "tm_p.h"
 
-/* Mips systems use the SDB functions to dump out symbols, but
-   do not supply usable syms.h include files.  */
-#if defined(USG) && !defined(MIPS)
+/* Mips systems use the SDB functions to dump out symbols, but do not
+   supply usable syms.h include files.  Which syms.h file to use is a
+   target parameter so don't use the native one if we're cross compiling.  */
+
+#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(__INTERIX) && !defined(CROSS_COMPILE)
 #include <syms.h>
 /* Use T_INT if we don't have T_VOID.  */
 #ifndef T_VOID
 #define T_VOID T_INT
 #endif
-#else /* not USG, or MIPS */
+#else
 #include "gsyms.h"
-#endif /* not USG, or MIPS */
+#endif
 
 /* #include <storclass.h>  used to be this instead of syms.h.  */
 
@@ -96,16 +104,24 @@ extern FILE *asm_out_file;
 
 extern tree current_function_decl;
 
-void sdbout_init ();
-void sdbout_symbol ();
-void sdbout_types();
+#include "sdbout.h"
 
-static void sdbout_typedefs ();
-static void sdbout_syms ();
-static void sdbout_one_type ();
-static void sdbout_queue_anonymous_type ();
-static void sdbout_dequeue_anonymous_type ();
-static int plain_type_1 ();
+static char *gen_fake_label            PARAMS ((void));
+static int plain_type                  PARAMS ((tree));
+static int template_name_p             PARAMS ((tree));
+static void sdbout_record_type_name    PARAMS ((tree));
+static int plain_type_1                        PARAMS ((tree, int));
+static void sdbout_block               PARAMS ((tree));
+static void sdbout_syms                        PARAMS ((tree));
+#ifdef SDB_ALLOW_FORWARD_REFERENCES
+static void sdbout_queue_anonymous_type        PARAMS ((tree));
+static void sdbout_dequeue_anonymous_types PARAMS ((void));
+#endif
+static void sdbout_type                        PARAMS ((tree));
+static void sdbout_field_types         PARAMS ((tree));
+static void sdbout_one_type            PARAMS ((tree));
+static void sdbout_parms               PARAMS ((tree));
+static void sdbout_reg_parms           PARAMS ((tree));
 \f
 /* Define the default sizes for various types.  */
 
@@ -161,7 +177,13 @@ static int plain_type_1 ();
 #endif
 
 #ifndef PUT_SDB_INT_VAL
-#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\t.val\t%d%s", (a), SDB_DELIM)
+#define PUT_SDB_INT_VAL(a) \
+ do {                                                                  \
+   fputs ("\t.val\t", asm_out_file);                                   \
+   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(a));        \
+   fprintf (asm_out_file, "%s", SDB_DELIM);                            \
+ } while (0)
+
 #endif
 
 #ifndef PUT_SDB_VAL
@@ -191,7 +213,12 @@ do { fprintf (asm_out_file, "\t.def\t");   \
 #endif
 
 #ifndef PUT_SDB_SIZE
-#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\t.size\t%d%s", a, SDB_DELIM)
+#define PUT_SDB_SIZE(a) \
+ do {                                                                  \
+   fputs ("\t.size\t", asm_out_file);                                  \
+   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(a));        \
+   fprintf (asm_out_file, "%s", SDB_DELIM);                            \
+ } while(0)
 #endif
 
 #ifndef PUT_SDB_START_DIM
@@ -258,12 +285,12 @@ do { fprintf (asm_out_file, "\t.def\t");          \
 /* Return the sdb tag identifier string for TYPE
    if TYPE has already been defined; otherwise return a null pointer.   */
 
-#define KNOWN_TYPE_TAG(type) (char *)(TYPE_SYMTAB_ADDRESS (type))
+#define KNOWN_TYPE_TAG(type)  TYPE_SYMTAB_POINTER (type)
 
 /* Set the sdb tag identifier string for TYPE to NAME.  */
 
 #define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
-  (TYPE_SYMTAB_ADDRESS (TYPE) = (int)(NAME))
+  TYPE_SYMTAB_POINTER (TYPE) = (NAME)
 
 /* Return the name (a string) of the struct, union or enum tag
    described by the TREE_LIST node LINK.  This is 0 for an anonymous one.  */
@@ -276,21 +303,60 @@ do { fprintf (asm_out_file, "\t.def\t");          \
 /* Ensure we don't output a negative line number.  */
 #define MAKE_LINE_SAFE(line)  \
   if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1
+
+/* Perform linker optimization of merging header file definitions together
+   for targets with MIPS_DEBUGGING_INFO defined.  This won't work without a
+   post 960826 version of GAS.  Nothing breaks with earlier versions of GAS,
+   the optimization just won't be done.  The native assembler already has the
+   necessary support.  */
+
+#ifdef MIPS_DEBUGGING_INFO
+
+#ifndef PUT_SDB_SRC_FILE
+#define PUT_SDB_SRC_FILE(FILENAME) \
+output_file_directive (asm_out_file, (FILENAME))
+#endif
+
+/* ECOFF linkers have an optimization that does the same kind of thing as
+   N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the
+   executable.  To achieve this, GCC must output a .file for each file
+   name change.  */
+
+/* This is a stack of input files.  */
+
+struct sdb_file
+{
+  struct sdb_file *next;
+  const char *name;
+};
+
+/* This is the top of the stack.  */
+
+static struct sdb_file *current_file;
+
+#endif /* MIPS_DEBUGGING_INFO */
 \f
 /* Set up for SDB output at the start of compilation.  */
 
 void
 sdbout_init (asm_file, input_file_name, syms)
-     FILE *asm_file;
-     char *input_file_name;
-     tree syms;
+     FILE *asm_file ATTRIBUTE_UNUSED;
+     const char *input_file_name ATTRIBUTE_UNUSED;
+     tree syms ATTRIBUTE_UNUSED;
 {
-#if 0 /* Nothing need be output for the predefined types.  */
-  /* Get all permanent types that have typedef names,
-     and output them all, except for those already output.  */
-
-  sdbout_typedefs (syms);
+#ifdef MIPS_DEBUGGING_INFO
+  current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
+  current_file->next = NULL;
+  current_file->name = input_file_name;
 #endif
+
+#ifdef RMS_QUICK_HACK_1
+  tree t;
+  for (t = syms; t; t = TREE_CHAIN (t))
+    if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
+       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
+      sdbout_symbol (t, 0);
+#endif  
 }
 
 #if 0
@@ -303,11 +369,10 @@ tag_of_ru_type (type,link)
      tree type,link;
 {
   if (TYPE_SYMTAB_ADDRESS (type))
-    return (char *)TYPE_SYMTAB_ADDRESS (type);
+    return TYPE_SYMTAB_ADDRESS (type);
   if (link && TREE_PURPOSE (link)
       && IDENTIFIER_POINTER (TREE_PURPOSE (link)))
-    TYPE_SYMTAB_ADDRESS (type)
-      = (int)IDENTIFIER_POINTER (TREE_PURPOSE (link));
+    TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
   else
     return (char *) TYPE_SYMTAB_ADDRESS (type);
 }
@@ -344,8 +409,10 @@ gen_fake_label ()
 /* Produce the number that describes a pointer, function or array type.
    PREV is the number describing the target, value or element type.
    DT_type describes how to transform that type.  */
-#define PUSH_DERIVED_LEVEL(DT_type,PREV) \
-  ((((PREV)&~N_BTMASK)<<N_TSHIFT)|(DT_type<<N_BTSHFT)|(PREV&N_BTMASK))
+#define PUSH_DERIVED_LEVEL(DT_type,PREV)               \
+  ((((PREV) & ~(int)N_BTMASK) << (int)N_TSHIFT)                \
+   | ((int)DT_type << (int)N_BTSHFT)                   \
+   | ((PREV) & (int)N_BTMASK))
 
 /* Number of elements used in sdb_dims.  */
 static int sdb_n_dims = 0;
@@ -360,7 +427,7 @@ static int
 plain_type (type)
      tree type;
 {
-  int val = plain_type_1 (type);
+  int val = plain_type_1 (type, 0);
 
   /* If we have already saved up some array dimensions, print them now.  */
   if (sdb_n_dims > 0)
@@ -387,6 +454,17 @@ plain_type (type)
   return val;
 }
 
+static int
+template_name_p (name)
+     tree name;
+{
+  register char *ptr = IDENTIFIER_POINTER (name);
+  while (*ptr && *ptr != '<')
+    ptr++;
+
+  return *ptr != '\0';
+}
+
 static void
 sdbout_record_type_name (type)
      tree type;
@@ -402,19 +480,19 @@ sdbout_record_type_name (type)
       tree t = 0;
       /* Find the IDENTIFIER_NODE for the type name.  */
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-       {
-         t = TYPE_NAME (type);
-       }
-#if 1  /* As a temprary hack, use typedef names for C++ only.  */
-      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-              && TYPE_LANG_SPECIFIC (type))
+       t = TYPE_NAME (type);
+      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
        {
          t = DECL_NAME (TYPE_NAME (type));
+         /* The DECL_NAME for templates includes "<>", which breaks
+            most assemblers.  Use its assembler name instead, which
+            has been mangled into being safe.  */
+         if (t && template_name_p (t))
+           t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
        }
-#endif
 
       /* Now get the name as a string, or invent one.  */
-      if (t != 0)
+      if (t != NULL_TREE)
        name = IDENTIFIER_POINTER (t);
     }
 
@@ -429,56 +507,120 @@ sdbout_record_type_name (type)
 #endif
 }
 
+/* Return the .type value for type TYPE.
+
+   LEVEL indicates how many levels deep we have recursed into the type.
+   The SDB debug format can only represent 6 derived levels of types.
+   After that, we must output inaccurate debug info.  We deliberately
+   stop before the 7th level, so that ADA recursive types will not give an
+   infinite loop.  */
+
 static int
-plain_type_1 (type)
+plain_type_1 (type, level)
      tree type;
+     int level;
 {
   if (type == 0)
     type = void_type_node;
-  if (type == error_mark_node)
+  else if (type == error_mark_node)
     type = integer_type_node;
-  type = TYPE_MAIN_VARIANT (type);
+  else
+    type = TYPE_MAIN_VARIANT (type);
 
   switch (TREE_CODE (type))
     {
     case VOID_TYPE:
       return T_VOID;
+    case BOOLEAN_TYPE:
     case INTEGER_TYPE:
       {
        int size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+       /* Carefully distinguish all the standard types of C,
+          without messing up if the language is not C.
+          Note that we check only for the names that contain spaces;
+          other names might occur by coincidence in other languages.  */
+       if (TYPE_NAME (type) != 0
+           && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+           && DECL_NAME (TYPE_NAME (type)) != 0
+           && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
+         {
+           char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+
+           if (!strcmp (name, "char"))
+             return T_CHAR;
+           if (!strcmp (name, "unsigned char"))
+             return T_UCHAR;
+           if (!strcmp (name, "signed char"))
+             return T_CHAR;
+           if (!strcmp (name, "int"))
+             return T_INT;
+           if (!strcmp (name, "unsigned int"))
+             return T_UINT;
+           if (!strcmp (name, "short int"))
+             return T_SHORT;
+           if (!strcmp (name, "short unsigned int"))
+             return T_USHORT;
+           if (!strcmp (name, "long int"))
+             return T_LONG;
+           if (!strcmp (name, "long unsigned int"))
+             return T_ULONG;
+         }
+
+       if (size == INT_TYPE_SIZE)
+         return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
        if (size == CHAR_TYPE_SIZE)
          return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
        if (size == SHORT_TYPE_SIZE)
          return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
-       if (size == INT_TYPE_SIZE)
-         return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
+       if (size == LONG_TYPE_SIZE)
+         return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
+       if (size == LONG_LONG_TYPE_SIZE)        /* better than nothing */
+         return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
        return 0;
       }
 
     case REAL_TYPE:
       {
-       int size = int_size_in_bytes (type) * BITS_PER_UNIT;
-       if (size == FLOAT_TYPE_SIZE)
+       int precision = TYPE_PRECISION (type);
+       if (precision == FLOAT_TYPE_SIZE)
          return T_FLOAT;
-       if (size == DOUBLE_TYPE_SIZE)
+       if (precision == DOUBLE_TYPE_SIZE)
          return T_DOUBLE;
+#ifdef EXTENDED_SDB_BASIC_TYPES
+       if (precision == LONG_DOUBLE_TYPE_SIZE)
+         return T_LNGDBL;
+#else
+       if (precision == LONG_DOUBLE_TYPE_SIZE)
+         return T_DOUBLE;      /* better than nothing */
+#endif
        return 0;
       }
 
     case ARRAY_TYPE:
       {
        int m;
-       m = plain_type_1 (TREE_TYPE (type));
+       if (level >= 6)
+         return T_VOID;
+       else
+         m = plain_type_1 (TREE_TYPE (type), level+1);
        if (sdb_n_dims < SDB_MAX_DIM)
          sdb_dims[sdb_n_dims++]
            = (TYPE_DOMAIN (type)
-              ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1
+              && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0
+              && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
+              && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
+              && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0)
+              ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
+                 - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1)
               : 0);
+
        return PUSH_DERIVED_LEVEL (DT_ARY, m);
       }
 
     case RECORD_TYPE:
     case UNION_TYPE:
+    case QUAL_UNION_TYPE:
     case ENUMERAL_TYPE:
       {
        char *tag;
@@ -497,8 +639,8 @@ plain_type_1 (type)
               only if the .def has already been finished.
               At least on 386, the Unix assembler
               cannot handle forward references to tags.  */
-           /* But the 88100, it requires them, sigh... */
-           /* And the MIPS requires unknown refs as well... */
+           /* But the 88100, it requires them, sigh...  */
+           /* And the MIPS requires unknown refs as well...  */
            tag = KNOWN_TYPE_TAG (type);
            PUT_SDB_TAG (tag);
            /* These 3 lines used to follow the close brace.
@@ -510,18 +652,27 @@ plain_type_1 (type)
          }
        return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
                : (TREE_CODE (type) == UNION_TYPE) ? T_UNION
+               : (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
                : T_ENUM);
       }
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       {
-       int m = plain_type_1 (TREE_TYPE (type));
+       int m;
+       if (level >= 6)
+         return T_VOID;
+       else
+         m = plain_type_1 (TREE_TYPE (type), level+1);
        return PUSH_DERIVED_LEVEL (DT_PTR, m);
       }
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       {
-       int m = plain_type_1 (TREE_TYPE (type));
+       int m;
+       if (level >= 6)
+         return T_VOID;
+       else
+         m = plain_type_1 (TREE_TYPE (type), level+1);
        return PUSH_DERIVED_LEVEL (DT_FCN, m);
       }
     default:
@@ -530,15 +681,12 @@ plain_type_1 (type)
 }
 \f
 /* Output the symbols defined in block number DO_BLOCK.
-   Set NEXT_BLOCK_NUMBER to 0 before calling.
 
    This function works by walking the tree structure of blocks,
    counting blocks until it finds the desired block.  */
 
 static int do_block = 0;
 
-static int next_block_number;
-
 static void
 sdbout_block (block)
      register tree block;
@@ -549,17 +697,13 @@ sdbout_block (block)
       if (TREE_USED (block))
        {
          /* When we reach the specified block, output its symbols.  */
-         if (next_block_number == do_block)
-           {
-             sdbout_syms (BLOCK_VARS (block));
-           }
+         if (BLOCK_NUMBER (block) == do_block)
+           sdbout_syms (BLOCK_VARS (block));
 
          /* If we are past the specified block, stop the scan.  */
-         if (next_block_number > do_block)
+         if (BLOCK_NUMBER (block) > do_block)
            return;
 
-         next_block_number++;
-
          /* Scan the blocks within this block.  */
          sdbout_block (BLOCK_SUBBLOCKS (block));
        }
@@ -590,7 +734,6 @@ sdbout_symbol (decl, local)
      tree decl;
      int local;
 {
-  int letter = 0;
   tree type = TREE_TYPE (decl);
   tree context = NULL_TREE;
   rtx value;
@@ -599,6 +742,12 @@ sdbout_symbol (decl, local)
 
   sdbout_one_type (type);
 
+#if 0 /* This loses when functions are marked to be ignored,
+        which happens in the C++ front end.  */
+  if (DECL_IGNORED_P (decl))
+    return;
+#endif
+
   switch (TREE_CODE (decl))
     {
     case CONST_DECL:
@@ -610,7 +759,10 @@ sdbout_symbol (decl, local)
       context = decl_function_context (decl);
       if (context == current_function_decl)
        return;
-      if (TREE_EXTERNAL (decl))
+      /* Check DECL_INITIAL to distinguish declarations from definitions.
+        Don't output debug info here for declarations; they will have
+        a DECL_INITIAL value of 0.  */
+      if (! DECL_INITIAL (decl))
        return;
       if (GET_CODE (DECL_RTL (decl)) != MEM
          || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
@@ -624,9 +776,14 @@ sdbout_symbol (decl, local)
       /* Done with tagged types.  */
       if (DECL_NAME (decl) == 0)
        return;
+      if (DECL_IGNORED_P (decl))
+       return;
 
       /* Output typedef name.  */
-      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
+      if (template_name_p (DECL_NAME (decl)))
+       PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+      else
+       PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
       PUT_SDB_SCL (C_TPDEF);
       break;
 
@@ -638,7 +795,11 @@ sdbout_symbol (decl, local)
     case VAR_DECL:
       /* Don't mention a variable that is external.
         Let the file that defines it describe it.  */
-      if (TREE_EXTERNAL (decl))
+      if (DECL_EXTERNAL (decl))
+       return;
+
+      /* Ignore __FUNCTION__, etc.  */
+      if (DECL_IGNORED_P (decl))
        return;
 
       /* If there was an error in the declaration, don't dump core
@@ -647,7 +808,12 @@ sdbout_symbol (decl, local)
       if (DECL_RTL (decl) == 0)
        return;
 
-      value = eliminate_regs (DECL_RTL (decl), 0, 0);
+      DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+#ifdef LEAF_REG_REMAP
+      if (current_function_uses_only_leaf_regs)
+       leaf_renumber_regs_insn (DECL_RTL (decl));
+#endif
+      value = DECL_RTL (decl);
 
       /* Don't mention a variable at all
         if it was completely optimized into nothingness.
@@ -659,11 +825,9 @@ sdbout_symbol (decl, local)
        {
          regno = REGNO (DECL_RTL (decl));
          if (regno >= FIRST_PSEUDO_REGISTER)
-           regno = reg_renumber[REGNO (DECL_RTL (decl))];
-         if (regno < 0)
            return;
        }
-      else if (GET_CODE (DECL_RTL (decl)) == SUBREG)
+      else if (GET_CODE (value) == SUBREG)
        {
          int offset = 0;
          while (GET_CODE (value) == SUBREG)
@@ -675,20 +839,28 @@ sdbout_symbol (decl, local)
            {
              regno = REGNO (value);
              if (regno >= FIRST_PSEUDO_REGISTER)
-               regno = reg_renumber[REGNO (value)];
-             if (regno >= 0)
-               regno += offset;
+               return;
+             regno += offset;
            }
+         alter_subreg (DECL_RTL (decl));
+         value = DECL_RTL (decl);
        }
+      /* Don't output anything if an auto variable
+        gets RTL that is static.
+        GAS version 2.2 can't handle such output.  */
+      else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
+              && ! TREE_STATIC (decl))
+       return;
 
       /* Emit any structure, union, or enum type that has not been output.
         This occurs for tag-less structs (et al) used to declare variables
         within functions.  */
       if (TREE_CODE (type) == ENUMERAL_TYPE
          || TREE_CODE (type) == RECORD_TYPE
-         || TREE_CODE (type) == UNION_TYPE)
+         || TREE_CODE (type) == UNION_TYPE
+         || TREE_CODE (type) == QUAL_UNION_TYPE)
        {
-         if (TYPE_SIZE (type) != 0             /* not a forward reference */
+         if (COMPLETE_TYPE_P (type)            /* not a forward reference */
              && KNOWN_TYPE_TAG (type) == 0)    /* not yet declared */
            sdbout_one_type (type);
        }
@@ -699,8 +871,13 @@ sdbout_symbol (decl, local)
          && DECL_INITIAL (decl))
        return;
 
+      /* C++ in 2.3 makes nameless symbols.  That will be fixed later.
+        For now, avoid crashing.  */
+      if (DECL_NAME (decl) == NULL_TREE)
+       return;
+
       /* Record the name for, starting a symtab entry.  */
-      name = IDENTIFIER_POINTER (DECL_NAME (decl));
+      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
 
       if (GET_CODE (value) == MEM
          && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
@@ -726,7 +903,7 @@ sdbout_symbol (decl, local)
       else if (GET_CODE (value) == MEM
               && (GET_CODE (XEXP (value, 0)) == MEM
                   || (GET_CODE (XEXP (value, 0)) == REG
-                      && REGNO (XEXP (value, 0)) != FRAME_POINTER_REGNUM
+                      && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
                       && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
        /* If the value is indirect by memory or by a register
           that isn't the frame pointer
@@ -751,15 +928,25 @@ sdbout_symbol (decl, local)
              PUT_SDB_SCL (C_AUTO);
            }
 
-         type = build_pointer_type (TREE_TYPE (decl));
+         /* Effectively do build_pointer_type, but don't cache this type,
+            since it might be temporary whereas the type it points to
+            might have been saved for inlining.  */
+         /* Don't use REFERENCE_TYPE because dbx can't handle that.  */
+         type = make_node (POINTER_TYPE);
+         TREE_TYPE (type) = TREE_TYPE (decl);
        }
       else if (GET_CODE (value) == MEM
-              && GET_CODE (XEXP (value, 0)) == PLUS
-              && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
-              && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
+              && ((GET_CODE (XEXP (value, 0)) == PLUS
+                   && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
+                   && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
+                  /* This is for variables which are at offset zero from
+                     the frame pointer.  This happens on the Alpha.
+                     Non-frame pointer registers are excluded above.  */
+                  || (GET_CODE (XEXP (value, 0)) == REG)))
        {
-         /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))).
-            We want the value of that CONST_INT.  */
+         /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
+            or (MEM (REG...)).  We want the value of that CONST_INT
+            or zero.  */
          PUT_SDB_DEF (name);
          PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
          PUT_SDB_SCL (C_AUTO);
@@ -787,6 +974,9 @@ sdbout_symbol (decl, local)
          return;
        }
       break;
+
+    default:
+      break;
     }
   PUT_SDB_TYPE (plain_type (type));
   PUT_SDB_ENDEF;
@@ -801,6 +991,9 @@ sdbout_toplevel_data (decl)
 {
   tree type = TREE_TYPE (decl);
 
+  if (DECL_IGNORED_P (decl))
+    return;
+
   if (! (TREE_CODE (decl) == VAR_DECL
         && GET_CODE (DECL_RTL (decl)) == MEM
         && DECL_INITIAL (decl)))
@@ -822,7 +1015,7 @@ sdbout_toplevel_data (decl)
 \f
 #ifdef SDB_ALLOW_FORWARD_REFERENCES
 
-/* Machinery to record and output anonymous types. */
+/* Machinery to record and output anonymous types.  */
 
 static tree anonymous_types;
 
@@ -847,7 +1040,7 @@ sdbout_dequeue_anonymous_types ()
        {
          register tree type = TREE_VALUE (link);
 
-         if (! TREE_ASM_WRITTEN (type))
+         if (type && ! TREE_ASM_WRITTEN (type))
            sdbout_one_type (type);
        }
     }
@@ -876,7 +1069,6 @@ static void
 sdbout_type (type)
      tree type;
 {
-  register tree tem;
   if (type == error_mark_node)
     type = integer_type_node;
   PUT_SDB_TYPE (plain_type (type));
@@ -893,11 +1085,20 @@ sdbout_field_types (type)
      tree type;
 {
   tree tail;
+
   for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
-    if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE)
-      sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
-    else
-      sdbout_one_type (TREE_TYPE (tail));
+    /* This condition should match the one for emitting the actual members
+       below.  */
+    if (TREE_CODE (tail) == FIELD_DECL
+       && DECL_NAME (tail) != 0
+       && ! host_integerp (DECL_SIZE (tail), 1)
+       && ! host_integerp (bit_position (tail), 0))
+      {
+       if (POINTER_TYPE_P (TREE_TYPE (tail)))
+         sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
+       else
+         sdbout_one_type (TREE_TYPE (tail));
+      }
 }
 
 /* Use this to put out the top level defined record and union types
@@ -911,12 +1112,17 @@ static void
 sdbout_one_type (type)
      tree type;
 {
-  text_section ();
+  if (current_function_decl != NULL_TREE
+      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
+    ; /* Don't change section amid function.  */
+  else
+    text_section ();
 
   switch (TREE_CODE (type))
     {
     case RECORD_TYPE:
     case UNION_TYPE:
+    case QUAL_UNION_TYPE:
     case ENUMERAL_TYPE:
       type = TYPE_MAIN_VARIANT (type);
       /* Don't output a type twice.  */
@@ -925,13 +1131,13 @@ sdbout_one_type (type)
        return;
 
       /* Output nothing if type is not yet defined.  */
-      if (TYPE_SIZE (type) == 0)
+      if (!COMPLETE_TYPE_P (type))
        return;
 
       TREE_ASM_WRITTEN (type) = 1;
 #if 1
       /* This is reputed to cause trouble with the following case,
-        but perhaps checking TYPE_SIZE above will fix it.
+        but perhaps checking TYPE_SIZE above will fix it.  */
 
       /* Here is a test case:
 
@@ -966,7 +1172,7 @@ sdbout_one_type (type)
       /* Output a structure type.  */
       {
        int size = int_size_in_bytes (type);
-       int member_scl;
+       int member_scl = 0;
        tree tem;
        int i, n_baseclasses = 0;
 
@@ -978,6 +1184,7 @@ sdbout_one_type (type)
        switch (TREE_CODE (type))
          {
          case UNION_TYPE:
+         case QUAL_UNION_TYPE:
            PUT_SDB_SCL (C_UNTAG);
            PUT_SDB_TYPE (T_UNION);
            member_scl = C_MOU;
@@ -994,6 +1201,9 @@ sdbout_one_type (type)
            PUT_SDB_TYPE (T_ENUM);
            member_scl = C_MOE;
            break;
+
+         default:
+           break;
          }
 
        PUT_SDB_SIZE (size);
@@ -1001,43 +1211,57 @@ sdbout_one_type (type)
 
        /* Print out the base class information with fields
           named after the types they hold.  */
-       if (TYPE_BINFO (type)
-           && TYPE_BINFO_BASETYPES (type))
-         n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
-       for (i = 0; i < n_baseclasses; i++)
+       /* This is only relevent to aggregate types.  TYPE_BINFO is used
+          for other purposes in an ENUMERAL_TYPE, so we must exclude that
+          case.  */
+       if (TREE_CODE (type) != ENUMERAL_TYPE)
          {
-           tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
-           tree child_type = BINFO_TYPE (child);
-           tree child_type_name;
-           if (TYPE_NAME (child_type) == 0)
-             continue;
-           if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
-             child_type_name = TYPE_NAME (child_type);
-           else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
-             child_type_name = DECL_NAME (TYPE_NAME (child_type));
-           else
-             continue;
+           if (TYPE_BINFO (type)
+               && TYPE_BINFO_BASETYPES (type))
+             n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
+           for (i = 0; i < n_baseclasses; i++)
+             {
+               tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)),
+                                          i);
+               tree child_type = BINFO_TYPE (child);
+               tree child_type_name;
+               if (TYPE_NAME (child_type) == 0)
+                 continue;
+               if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
+                 child_type_name = TYPE_NAME (child_type);
+               else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
+                 {
+                   child_type_name = DECL_NAME (TYPE_NAME (child_type));
+                   if (child_type_name && template_name_p (child_type_name))
+                     child_type_name
+                       = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
+                 }
+               else
+                 continue;
 
-           CONTIN;
-           PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
-           PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));
-           PUT_SDB_SCL (member_scl);
-           sdbout_type (BINFO_TYPE (child));
-           PUT_SDB_ENDEF;
+               CONTIN;
+               PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
+               PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0));
+               PUT_SDB_SCL (member_scl);
+               sdbout_type (BINFO_TYPE (child));
+               PUT_SDB_ENDEF;
+             }
          }
 
        /* output the individual fields */
 
        if (TREE_CODE (type) == ENUMERAL_TYPE)
-         for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
-           {
-             PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
-             PUT_SDB_INT_VAL (TREE_INT_CST_LOW (TREE_VALUE (tem)));
-             PUT_SDB_SCL (C_MOE);
-             PUT_SDB_TYPE (T_MOE);
-             PUT_SDB_ENDEF;
-           }
-
+         {
+           for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+             if (host_integerp (TREE_VALUE (tem), 0))
+               {
+                 PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
+                 PUT_SDB_INT_VAL (tree_low_cst (TREE_VALUE (tem), 0));
+                 PUT_SDB_SCL (C_MOE);
+                 PUT_SDB_TYPE (T_MOE);
+                 PUT_SDB_ENDEF;
+               }
+         }
        else                    /* record or union type */
          for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
            /* Output the name, type, position (in bits), size (in bits)
@@ -1048,22 +1272,24 @@ sdbout_one_type (type)
               Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
            if (TREE_CODE (tem) == FIELD_DECL
                && DECL_NAME (tem) != 0
-               && TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST
-               && TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)
+               && host_integerp (DECL_SIZE (tem), 1)
+               && host_integerp (bit_position (tem), 0))
              {
+               char *name;
+
                CONTIN;
-               PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (tem)));
+               name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem));
+               PUT_SDB_DEF (name);
                if (DECL_BIT_FIELD_TYPE (tem))
                  {
-                   PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));
+                   PUT_SDB_INT_VAL (int_bit_position (tem));
                    PUT_SDB_SCL (C_FIELD);
                    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
-                   PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem)));
+                   PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1));
                  }
                else
                  {
-                   PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))
-                                    / BITS_PER_UNIT);
+                   PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT);
                    PUT_SDB_SCL (member_scl);
                    sdbout_type (TREE_TYPE (tem));
                  }
@@ -1078,6 +1304,9 @@ sdbout_one_type (type)
        PUT_SDB_SIZE (size);
        PUT_SDB_ENDEF;
        break;
+
+      default:
+       break;
       }
     }
 }
@@ -1109,9 +1338,9 @@ sdbout_parms (parms)
 
        /* Perform any necessary register eliminations on the parameter's rtl,
           so that the debugging output will be accurate.  */
-       DECL_INCOMING_RTL (parms) =
-         eliminate_regs (DECL_INCOMING_RTL (parms), 0, 0);
-       DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, 0);
+       DECL_INCOMING_RTL (parms)
+         = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
+       DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
 
        if (PARM_PASSED_IN_MEMORY (parms))
          {
@@ -1129,7 +1358,6 @@ sdbout_parms (parms)
              current_sym_value = 0;
 
            if (GET_CODE (DECL_RTL (parms)) == REG
-               && REGNO (DECL_RTL (parms)) >= 0
                && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
              type = DECL_ARG_TYPE (parms);
            else
@@ -1142,12 +1370,12 @@ sdbout_parms (parms)
                   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))
+               if (BYTES_BIG_ENDIAN
+                   && 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))
@@ -1177,8 +1405,7 @@ sdbout_parms (parms)
               pretend the parm was passed there.  It would be more consistent
               to describe the register where the parm was passed,
               but in practice that register usually holds something else.  */
-           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);
            /* If the parm lives nowhere,
               use the register where it was passed.  */
@@ -1188,7 +1415,7 @@ sdbout_parms (parms)
            PUT_SDB_DEF (name);
            PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
            PUT_SDB_SCL (C_REGPARM);
-           PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+           PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
            PUT_SDB_ENDEF;
          }
        else if (GET_CODE (DECL_RTL (parms)) == MEM
@@ -1211,7 +1438,7 @@ sdbout_parms (parms)
            PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
                                                  XEXP (DECL_RTL (parms), 0)));
            PUT_SDB_SCL (C_ARG);
-           PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+           PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
            PUT_SDB_ENDEF;
          }
       }
@@ -1240,7 +1467,6 @@ sdbout_reg_parms (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))
          {
@@ -1249,7 +1475,7 @@ sdbout_reg_parms (parms)
            PUT_SDB_DEF (name);
            PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
            PUT_SDB_SCL (C_REG);
-           PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+           PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
            PUT_SDB_ENDEF;
          }
        /* Report parms that live in memory but not where they were passed.  */
@@ -1264,11 +1490,11 @@ sdbout_reg_parms (parms)
            /* 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))
+           if (BYTES_BIG_ENDIAN
+               && 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
              {
@@ -1295,25 +1521,31 @@ sdbout_reg_parms (parms)
 
 void
 sdbout_begin_block (file, line, n)
-     FILE *file;
+     FILE *file ATTRIBUTE_UNUSED;
      int line;
      int n;
 {
   tree decl = current_function_decl;
   MAKE_LINE_SAFE (line);
-  PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
+
+  /* The SCO compiler does not emit a separate block for the function level
+     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
+     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
+#ifndef MIPS_DEBUGGING_INFO
+  if (n != 1)
+#endif
+    PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
+
   if (n == 1)
     {
       /* Include the outermost BLOCK's variables in block 1.  */
-      next_block_number = 0;
-      do_block = 0;
+      do_block = BLOCK_NUMBER (DECL_INITIAL (decl));
       sdbout_block (DECL_INITIAL (decl));
     }
   /* If -g1, suppress all the internal symbols of functions
      except for arguments.  */
   if (debug_info_level != DINFO_LEVEL_TERSE)
     {
-      next_block_number = 0;
       do_block = n;
       sdbout_block (DECL_INITIAL (decl));
     }
@@ -1326,11 +1558,19 @@ sdbout_begin_block (file, line, n)
 /* Describe the end line-number of an internal block within a function.  */
 
 void
-sdbout_end_block (file, line)
-     FILE *file;
+sdbout_end_block (file, line, n)
+     FILE *file ATTRIBUTE_UNUSED;
      int line;
+     int n ATTRIBUTE_UNUSED;
 {
   MAKE_LINE_SAFE (line);
+
+  /* The SCO compiler does not emit a separate block for the function level
+     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
+     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
+#ifndef MIPS_DEBUGGING_INFO
+  if (n != 1)
+#endif
   PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
 }
 
@@ -1401,4 +1641,35 @@ sdbout_label (insn)
   PUT_SDB_ENDEF;
 }
 
+/* Change to reading from a new source file.  */
+
+void
+sdbout_start_new_source_file (filename)
+     const char *filename ATTRIBUTE_UNUSED;
+{
+#ifdef MIPS_DEBUGGING_INFO
+  struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
+
+  n->next = current_file;
+  n->name = filename;
+  current_file = n;
+  PUT_SDB_SRC_FILE (filename);
+#endif
+}
+
+/* Revert to reading a previous source file.  */
+
+void
+sdbout_resume_previous_source_file ()
+{
+#ifdef MIPS_DEBUGGING_INFO
+  struct sdb_file *next;
+
+  next = current_file->next;
+  free (current_file);
+  current_file = next;
+  PUT_SDB_SRC_FILE (current_file->name);
+#endif
+}
+
 #endif /* SDB_DEBUGGING_INFO */