OSDN Git Service

PR debug/31510
[pf3gnuchains/gcc-fork.git] / gcc / dbxout.c
index 7a9cb60..8b11a9a 100644 (file)
@@ -1,12 +1,13 @@
 /* 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, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* Output dbx-format symbol table data.
@@ -89,6 +89,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "target.h"
 #include "langhooks.h"
 #include "obstack.h"
+#include "expr.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"
@@ -241,13 +242,6 @@ static GTY(()) int scope_labelno;
 
 static GTY(()) int dbxout_source_line_counter;
 
-/* Nonzero if we have actually used any of the GDB extensions
-   to the debugging format.  The idea is that we use them for the
-   first time only if there's a strong reason, but once we have done that,
-   we use them whenever convenient.  */
-
-static GTY(()) int have_used_extensions = 0;
-
 /* Number for the next N_SOL filename stabs label.  The number 0 is reserved
    for the N_SO filename stabs label.  */
 
@@ -275,7 +269,7 @@ static int pending_bincls = 0;
 static const char *base_input_file;
 
 #ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT function_section (current_function_decl);
+#define FORCE_TEXT switch_to_section (current_function_section ())
 #else
 #define FORCE_TEXT
 #endif
@@ -332,7 +326,6 @@ static void dbxout_type_name (tree);
 static void dbxout_class_name_qualifiers (tree);
 static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
-static void dbxout_block (tree, int, tree);
 static void dbxout_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
@@ -359,7 +352,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_end_source_file,
   dbxout_begin_block,
   dbxout_end_block,
-  debug_true_tree,                      /* ignore_block */
+  debug_true_const_tree,                /* ignore_block */
   dbxout_source_line,                   /* source_line */
   dbxout_begin_prologue,                /* begin_prologue */
   debug_nothing_int_charstar,           /* end_prologue */
@@ -378,7 +371,9 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   debug_nothing_tree,                   /* outlining_inline_function */
   debug_nothing_rtx,                    /* label */
   dbxout_handle_pch,                    /* handle_pch */
-  debug_nothing_rtx                     /* var_location */
+  debug_nothing_rtx,                    /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
+  0                                      /* start_end_main_source_file */
 };
 #endif /* DBX_DEBUGGING_INFO  */
 
@@ -393,7 +388,7 @@ 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_const_tree,                /* ignore_block */
   xcoffout_source_line,
   xcoffout_begin_prologue,              /* begin_prologue */
   debug_nothing_int_charstar,           /* end_prologue */
@@ -408,7 +403,9 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   debug_nothing_tree,                   /* outlining_inline_function */
   debug_nothing_rtx,                    /* label */
   dbxout_handle_pch,                    /* handle_pch */
-  debug_nothing_rtx                     /* var_location */
+  debug_nothing_rtx,                    /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
+  0                                      /* start_end_main_source_file */
 };
 #endif /* XCOFF_DEBUGGING_INFO  */
 \f
@@ -859,7 +856,7 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
       obstack_1grow (&stabstr_ob, '\0');
 
       len = obstack_object_size (&stabstr_ob);
-      chunk = str = obstack_finish (&stabstr_ob);
+      chunk = str = XOBFINISH (&stabstr_ob, char *);
 
       /* Within the buffer are a sequence of NUL-separated strings,
         each of which is to be written out as a separate stab
@@ -892,7 +889,7 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
         comma than to do a two-character fputs.  */
       obstack_grow (&stabstr_ob, "\",", 2);
       len = obstack_object_size (&stabstr_ob);
-      str = obstack_finish (&stabstr_ob);
+      str = XOBFINISH (&stabstr_ob, char *);
       
       fwrite (str, 1, len, asm_out_file);
       DBX_FINISH_STABS (sym, code, line, addr, label, number);
@@ -907,36 +904,44 @@ dbxout_function_end (tree decl)
 {
   char lscope_label_name[100];
 
-  /* 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
-      || DECL_IGNORED_P (decl))
-    return;
-
   /* The Lscope label must be emitted even if we aren't doing anything
      else; dbxout_block needs it.  */
-  function_section (current_function_decl);
+  switch_to_section (function_section (current_function_decl));
   
   /* Convert Lscope 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 (asm_out_file, "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
+      || DECL_IGNORED_P (decl))
+    return;
 
   /* 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 (asm_out_file, lscope_label_name, current_function_decl);
-#else
-  dbxout_begin_empty_stabs (N_FUN);
-  dbxout_stab_value_label_diff (lscope_label_name,
-                               XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
-                               
-#endif
+  if (flag_reorder_blocks_and_partition)
+    {
+      dbxout_begin_empty_stabs (N_FUN);
+      dbxout_stab_value_label_diff (cfun->hot_section_end_label, 
+                                   cfun->hot_section_label);
+      dbxout_begin_empty_stabs (N_FUN);
+      dbxout_stab_value_label_diff (cfun->cold_section_end_label, 
+                                   cfun->cold_section_label);
+    }
+  else
+    {
+      char begin_label[20];
+      /* Reference current function start using LFBB.  */
+      ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+      dbxout_begin_empty_stabs (N_FUN);
+      dbxout_stab_value_label_diff (lscope_label_name, begin_label);
+    }
 
   if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols)
     dbxout_stabd (N_ENSYM, 0);
@@ -961,6 +966,8 @@ get_lang_number (void)
     return N_SO_PASCAL;
   else if (strcmp (language_string, "GNU Objective-C") == 0)
     return N_SO_OBJC;
+  else if (strcmp (language_string, "GNU Objective-C++") == 0)
+    return N_SO_OBJCPLUS;
   else
     return 0;
 
@@ -975,6 +982,7 @@ dbxout_init (const char *input_file_name)
   char ltext_label_name[100];
   bool used_ltext_label_name = false;
   tree syms = lang_hooks.decls.getdecls ();
+  const char *mapped_name;
 
   typevec_len = 100;
   typevec = ggc_calloc (typevec_len, sizeof typevec[0]);
@@ -1000,6 +1008,7 @@ dbxout_init (const char *input_file_name)
            cwd = "/";
          else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1]))
            cwd = concat (cwd, "/", NULL);
+         cwd = remap_debug_filename (cwd);
        }
 #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
       DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd);
@@ -1010,17 +1019,18 @@ dbxout_init (const char *input_file_name)
 #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
     }
 
+  mapped_name = remap_debug_filename (input_file_name);
 #ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
-  DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, input_file_name);
+  DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, mapped_name);
 #else
-  dbxout_begin_simple_stabs_desc (input_file_name, N_SO, get_lang_number ());
+  dbxout_begin_simple_stabs_desc (mapped_name, N_SO, get_lang_number ());
   dbxout_stab_value_label (ltext_label_name);
   used_ltext_label_name = true;
 #endif
 
   if (used_ltext_label_name)
     {
-      text_section ();
+      switch_to_section (text_section);
       targetm.asm_out.internal_label (asm_out_file, "Ltext", 0);
     }
 
@@ -1036,7 +1046,7 @@ dbxout_init (const char *input_file_name)
   next_type_number = 1;
 
 #ifdef DBX_USE_BINCL
-  current_file = xmalloc (sizeof *current_file);
+  current_file = XNEW (struct dbx_file);
   current_file->next = NULL;
   current_file->file_number = 0;
   current_file->next_type_number = 1;
@@ -1145,7 +1155,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
                          const char *filename ATTRIBUTE_UNUSED)
 {
 #ifdef DBX_USE_BINCL
-  struct dbx_file *n = xmalloc (sizeof *n);
+  struct dbx_file *n = XNEW (struct dbx_file);
 
   n->next = current_file;
   n->next_type_number = 1;
@@ -1155,7 +1165,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
   n->prev = NULL;
   current_file->prev = n;
   n->bincl_status = BINCL_PENDING;
-  n->pending_bincl_name = filename;
+  n->pending_bincl_name = remap_debug_filename (filename);
   pending_bincls = 1;
   current_file = n;
 #endif
@@ -1204,6 +1214,9 @@ dbxout_handle_pch (unsigned at_end)
 }
 
 #if defined (DBX_DEBUGGING_INFO)
+
+static void dbxout_block (tree, int, tree);
+
 /* Output debugging info to FILE to switch to sourcefile FILENAME.  */
 
 static void
@@ -1219,15 +1232,16 @@ dbxout_source_file (const char *filename)
     {
       /* Don't change section amid function.  */
       if (current_function_decl == NULL_TREE)
-       text_section ();
+       switch_to_section (text_section);
 
-      dbxout_begin_simple_stabs (filename, N_SOL);
+      dbxout_begin_simple_stabs (remap_debug_filename (filename), N_SOL);
       dbxout_stab_value_internal_label ("Ltext", &source_label_number);
       lastfile = filename;
     }
 }
 
-/* Output N_BNSYM and line number symbol entry.  */
+/* Output N_BNSYM, line number symbol entry, and local symbol at 
+   function scope  */
 
 static void
 dbxout_begin_prologue (unsigned int lineno, const char *filename)
@@ -1238,7 +1252,14 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename)
       && !flag_debug_only_used_symbols)
     dbxout_stabd (N_BNSYM, 0);
 
+  /* pre-increment the scope counter */
+  scope_labelno++;
+
   dbxout_source_line (lineno, filename);
+  /* Output function begin block at function scope, referenced 
+     by dbxout_block, dbxout_source_line and dbxout_function_end.  */
+  emit_pending_bincls_if_required ();
+  targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno);
 }
 
 /* Output a line number symbol entry for source file FILENAME and line
@@ -1254,11 +1275,12 @@ dbxout_source_line (unsigned int lineno, const char *filename)
 #else
   if (DBX_LINES_FUNCTION_RELATIVE)
     {
-      rtx begin_label = XEXP (DECL_RTL (current_function_decl), 0);
+      char begin_label[20];
       dbxout_begin_stabn_sline (lineno);
+      /* Reference current function start using LFBB.  */
+      ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); 
       dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter,
-                                            XSTR (begin_label, 0));
-
+                                            begin_label);
     }
   else
     dbxout_stabd (N_SLINE, lineno);
@@ -1307,9 +1329,7 @@ dbxout_function_decl (tree decl)
 static void
 dbxout_global_decl (tree decl)
 {
-  if (TREE_CODE (decl) == VAR_DECL
-      && ! DECL_EXTERNAL (decl)
-      && DECL_RTL_SET_P (decl))        /* Not necessary?  */
+  if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
       int saved_tree_used = TREE_USED (decl);
       TREE_USED (decl) = 1;
@@ -1336,7 +1356,7 @@ dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
   DBX_OUTPUT_MAIN_SOURCE_FILE_END (asm_out_file, filename);
 #elif defined DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
  {
-   text_section ();
+   switch_to_section (text_section);
    dbxout_begin_empty_stabs (N_SO);
    dbxout_stab_value_internal_label ("Letext", 0);
  }
@@ -1388,14 +1408,14 @@ dbxout_type_fields (tree type)
 
       /* Omit here local type decls until we know how to support them.  */
       if (TREE_CODE (tem) == TYPE_DECL
+         /* Omit here the nameless fields that are used to skip bits.  */
+         || DECL_IGNORED_P (tem)
          /* Omit fields whose position or size are variable or too large to
             represent.  */
          || (TREE_CODE (tem) == FIELD_DECL
              && (! host_integerp (bit_position (tem), 0)
                  || ! DECL_SIZE (tem)
-                 || ! host_integerp (DECL_SIZE (tem), 1)))
-         /* Omit here the nameless fields that are used to skip bits.  */
-          || DECL_IGNORED_P (tem))
+                 || ! host_integerp (DECL_SIZE (tem), 1))))
        continue;
 
       else if (TREE_CODE (tem) != CONST_DECL)
@@ -1413,7 +1433,6 @@ dbxout_type_fields (tree type)
              && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem)
                  || TREE_CODE (tem) != FIELD_DECL))
            {
-             have_used_extensions = 1;
              stabstr_C ('/');
              stabstr_C (DECL_ACCESSIBILITY_CHAR (tem));
            }
@@ -1428,7 +1447,6 @@ dbxout_type_fields (tree type)
                {
                  tree name = DECL_ASSEMBLER_NAME (tem);
 
-                 have_used_extensions = 1;
                  stabstr_C (':');
                  stabstr_I (name);
                  stabstr_C (';');
@@ -1636,11 +1654,15 @@ dbxout_type (tree type, int full)
   tree tem;
   tree main_variant;
   static int anonymous_type_number = 0;
+  bool vector_type = false;
 
   if (TREE_CODE (type) == VECTOR_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)));
+    {
+      /* 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)));
+      vector_type = true;
+    }
 
   /* If there was an input error and we don't really have a type,
      avoid crashing and write something that is at least valid
@@ -1839,7 +1861,6 @@ dbxout_type (tree type, int full)
          if (use_gnu_debug_info_extensions
              && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
            {
-             have_used_extensions = 1;
              stabstr_S ("@s");
              stabstr_D (TYPE_PRECISION (type));
              stabstr_C (';');
@@ -1856,7 +1877,6 @@ dbxout_type (tree type, int full)
          if (use_gnu_debug_info_extensions
              && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
            {
-             have_used_extensions = 1;
              stabstr_S ("@s");
              stabstr_D (TYPE_PRECISION (type));
              stabstr_C (';');
@@ -1891,6 +1911,7 @@ dbxout_type (tree type, int full)
       break;
 
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       /* This used to say `r1' and we used to take care
         to make sure that `int' was type number 1.  */
       stabstr_C ('r');
@@ -1900,28 +1921,9 @@ dbxout_type (tree type, int full)
       stabstr_S (";0;");
       break;
 
-    case CHAR_TYPE:
-      if (use_gnu_debug_info_extensions)
-       {
-         have_used_extensions = 1;
-         stabstr_S ("@s");
-         stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
-         stabstr_S (";-20;");
-       }
-      else
-       {
-         /* Output the type `char' as a subrange of itself.
-            That is what pcc seems to do.  */
-         stabstr_C ('r');
-         dbxout_type_index (char_type_node);
-         stabstr_S (TYPE_UNSIGNED (type) ? ";0;255;" : ";0;127;");
-       }
-      break;
-
     case BOOLEAN_TYPE:
       if (use_gnu_debug_info_extensions)
        {
-         have_used_extensions = 1;
          stabstr_S ("@s");
          stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
          stabstr_S (";-16;");
@@ -1930,11 +1932,6 @@ dbxout_type (tree type, int full)
        stabstr_S ("eFalse:0,True:1,;");
       break;
 
-    case FILE_TYPE:
-      stabstr_C ('d');
-      dbxout_type (TREE_TYPE (type), 0);
-      break;
-
     case COMPLEX_TYPE:
       /* 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_*
@@ -1972,7 +1969,6 @@ dbxout_type (tree type, int full)
       /* Make arrays of packed bits look like bitstrings for chill.  */
       if (TYPE_PACKED (type) && use_gnu_debug_info_extensions)
        {
-         have_used_extensions = 1;
          stabstr_S ("@s");
          stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
          stabstr_S (";@S;S");
@@ -1980,6 +1976,9 @@ dbxout_type (tree type, int full)
          break;
        }
 
+      if (use_gnu_debug_info_extensions && vector_type)
+       stabstr_S ("@V;");
+
       /* Output "a" followed by a range type definition
         for the index type of the array
         followed by a reference to the target-type.
@@ -1988,7 +1987,6 @@ dbxout_type (tree type, int full)
         different from an array of characters.  */
       if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
        {
-         have_used_extensions = 1;
          stabstr_S ("@S;");
        }
       tem = TYPE_DOMAIN (type);
@@ -2031,7 +2029,11 @@ dbxout_type (tree type, int full)
               another type's definition; instead, output an xref
               and let the definition come when the name is defined.  */
            stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
-           if (TYPE_NAME (type) != 0)
+           if (TYPE_NAME (type) != 0
+               /* The C frontend creates for anonymous variable length
+                  records/unions TYPE_NAME with DECL_NAME NULL.  */
+               && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
+                   || DECL_NAME (TYPE_NAME (type))))
              dbxout_type_name (type);
            else
              {
@@ -2052,13 +2054,12 @@ dbxout_type (tree type, int full)
          {
            int i;
            tree child;
-           VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo);
+           VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
            
            if (use_gnu_debug_info_extensions)
              {
                if (BINFO_N_BASE_BINFOS (binfo))
                  {
-                   have_used_extensions = 1;
                    stabstr_C ('!');
                    stabstr_U (BINFO_N_BASE_BINFOS (binfo));
                    stabstr_C (',');
@@ -2071,13 +2072,13 @@ dbxout_type (tree type, int full)
 
                if (use_gnu_debug_info_extensions)
                  {
-                   have_used_extensions = 1;
                    stabstr_C (BINFO_VIRTUAL_P (child) ? '1' : '0');
                    stabstr_C (access == access_public_node ? '2' :
                                   access == access_protected_node
                                   ? '1' :'0');
                    if (BINFO_VIRTUAL_P (child)
-                       && strcmp (lang_hooks.name, "GNU C++") == 0)
+                       && (strcmp (lang_hooks.name, "GNU C++") == 0
+                           || strcmp (lang_hooks.name, "GNU Objective-C++") == 0))
                      /* For a virtual base, print the (negative)
                         offset within the vtable where we must look
                         to find the necessary adjustment.  */
@@ -2116,7 +2117,6 @@ dbxout_type (tree type, int full)
       dbxout_type_fields (type);
       if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
        {
-         have_used_extensions = 1;
          dbxout_type_methods (type);
        }
 
@@ -2126,7 +2126,6 @@ dbxout_type (tree type, int full)
          /* Avoid the ~ if we don't really need it--it confuses dbx.  */
          && TYPE_VFIELD (type))
        {
-         have_used_extensions = 1;
 
          /* We need to write out info about what field this class
             uses as its "main" vtable pointer field, because if this
@@ -2157,7 +2156,6 @@ dbxout_type (tree type, int full)
       if (use_gnu_debug_info_extensions
          && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
        {
-         have_used_extensions = 1;
          stabstr_S ("@s");
          stabstr_D (TYPE_PRECISION (type));
          stabstr_C (';');
@@ -2193,7 +2191,6 @@ dbxout_type (tree type, int full)
     case METHOD_TYPE:
       if (use_gnu_debug_info_extensions)
        {
-         have_used_extensions = 1;
          stabstr_C ('#');
 
          /* Write the argument types out longhand.  */
@@ -2211,7 +2208,6 @@ dbxout_type (tree type, int full)
     case OFFSET_TYPE:
       if (use_gnu_debug_info_extensions)
        {
-         have_used_extensions = 1;
          stabstr_C ('@');
          dbxout_type (TYPE_OFFSET_BASETYPE (type), 0);
          stabstr_C (',');
@@ -2225,7 +2221,6 @@ dbxout_type (tree type, int full)
     case REFERENCE_TYPE:
       if (use_gnu_debug_info_extensions)
        {
-         have_used_extensions = 1;
          stabstr_C ('&');
        }
       else
@@ -2326,6 +2321,149 @@ dbxout_class_name_qualifiers (tree decl)
     }
 }
 \f
+/* This is a specialized subset of expand_expr for use by dbxout_symbol in
+   evaluating DECL_VALUE_EXPR.  In particular, we stop if we find decls that
+   havn't been expanded, or if the expression is getting so complex we won't
+   be able to represent it in stabs anyway.  Returns NULL on failure.  */
+
+static rtx
+dbxout_expand_expr (tree expr)
+{
+  switch (TREE_CODE (expr))
+    {
+    case VAR_DECL:
+      /* We can't handle emulated tls variables, because the address is an
+        offset to the return value of __emutls_get_address, and there is no
+        way to express that in stabs.  Also, there are name mangling issues
+        here.  We end up with references to undefined symbols if we don't
+        disable debug info for these variables.  */
+      if (!targetm.have_tls && DECL_THREAD_LOCAL_P (expr))
+       return NULL;
+      /* FALLTHRU */
+
+    case PARM_DECL:
+      if (DECL_HAS_VALUE_EXPR_P (expr))
+       return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
+      /* FALLTHRU */
+
+    case CONST_DECL:
+    case RESULT_DECL:
+      return DECL_RTL_IF_SET (expr);
+
+    case INTEGER_CST:
+      return expand_expr (expr, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+
+    case COMPONENT_REF:
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+    case BIT_FIELD_REF:
+      {
+       enum machine_mode mode;
+       HOST_WIDE_INT bitsize, bitpos;
+       tree offset, tem;
+       int volatilep = 0, unsignedp = 0;
+       rtx x;
+
+       tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
+                                  &mode, &unsignedp, &volatilep, true);
+
+       x = dbxout_expand_expr (tem);
+       if (x == NULL || !MEM_P (x))
+         return NULL;
+       if (offset != NULL)
+         {
+           if (!host_integerp (offset, 0))
+             return NULL;
+           x = adjust_address_nv (x, mode, tree_low_cst (offset, 0));
+         }
+       if (bitpos != 0)
+         x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT);
+
+       return x;
+      }
+
+    default:
+      return NULL;
+    }
+}
+
+/* Helper function for output_used_types.  Queue one entry from the
+   used types hash to be output.  */
+
+static int
+output_used_types_helper (void **slot, void *data)
+{
+  tree type = *slot;
+  VEC(tree, heap) **types_p = data;
+
+  if ((TREE_CODE (type) == RECORD_TYPE
+       || TREE_CODE (type) == UNION_TYPE
+       || TREE_CODE (type) == QUAL_UNION_TYPE
+       || TREE_CODE (type) == ENUMERAL_TYPE)
+      && TYPE_STUB_DECL (type)
+      && DECL_P (TYPE_STUB_DECL (type))
+      && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
+    VEC_quick_push (tree, *types_p, TYPE_STUB_DECL (type));
+  else if (TYPE_NAME (type)
+          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+    VEC_quick_push (tree, *types_p, TYPE_NAME (type));
+
+  return 1;
+}
+
+/* This is a qsort callback which sorts types and declarations into a
+   predictable order (types, then declarations, sorted by UID
+   within).  */
+
+static int
+output_types_sort (const void *pa, const void *pb)
+{
+  const tree lhs = *((const tree *)pa);
+  const tree rhs = *((const tree *)pb);
+
+  if (TYPE_P (lhs))
+    {
+      if (TYPE_P (rhs))
+       return TYPE_UID (lhs) - TYPE_UID (rhs);
+      else
+       return 1;
+    }
+  else
+    {
+      if (TYPE_P (rhs))
+       return -1;
+      else
+       return DECL_UID (lhs) - DECL_UID (rhs);
+    }
+}
+
+
+/* Force all types used by this function to be output in debug
+   information.  */
+
+static void
+output_used_types (void)
+{
+  if (cfun && cfun->used_types_hash)
+    {
+      VEC(tree, heap) *types;
+      int i;
+      tree type;
+
+      types = VEC_alloc (tree, heap, htab_elements (cfun->used_types_hash));
+      htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
+
+      /* Sort by UID to prevent dependence on hash table ordering.  */
+      qsort (VEC_address (tree, types), VEC_length (tree, types),
+            sizeof (tree), output_types_sort);
+
+      for (i = 0; VEC_iterate (tree, types, i, type); i++)
+       debug_queue_symbol (type);
+
+      VEC_free (tree, heap, types);
+    }
+}
+
 /* Output a .stabs for the symbol defined by DECL,
    which must be a ..._DECL node in the normal namespace.
    It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
@@ -2338,6 +2476,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
   tree type = TREE_TYPE (decl);
   tree context = NULL_TREE;
   int result = 0;
+  rtx decl_rtl;
 
   /* "Intercept" dbxout_symbol() calls like we do all debug_hooks.  */
   ++debug_nesting;
@@ -2349,7 +2488,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
     DBXOUT_DECR_NESTING_AND_RETURN (0);
 
   /* If we are to generate only the symbols actually used then such
-     symbol nodees are flagged with TREE_USED.  Ignore any that
+     symbol nodes are flagged with TREE_USED.  Ignore any that
      aren't flaged as TREE_USED.  */
 
   if (flag_debug_only_used_symbols
@@ -2422,7 +2561,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       break;
 
     case FUNCTION_DECL:
-      if (DECL_RTL (decl) == 0)
+      decl_rtl = DECL_RTL_IF_SET (decl);
+      if (!decl_rtl)
        DBXOUT_DECR_NESTING_AND_RETURN (0);
       if (DECL_EXTERNAL (decl))
        break;
@@ -2433,10 +2573,13 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       /* Don't mention an inline instance of a nested function.  */
       if (context && DECL_FROM_INLINE (decl))
        break;
-      if (!MEM_P (DECL_RTL (decl))
-         || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
+      if (!MEM_P (decl_rtl)
+         || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF)
        break;
 
+      if (flag_debug_only_used_symbols)
+       output_used_types ();
+
       dbxout_begin_complex_stabs ();
       stabstr_I (DECL_ASSEMBLER_NAME (decl));
       stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f");
@@ -2458,8 +2601,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
          stabstr_I (DECL_NAME (context));
        }
 
-      dbxout_finish_complex_stabs (decl, N_FUN, XEXP (DECL_RTL (decl), 0),
-                                  0, 0);
+      dbxout_finish_complex_stabs (decl, N_FUN, XEXP (decl_rtl, 0), 0, 0);
       break;
 
     case TYPE_DECL:
@@ -2501,7 +2643,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
                 || TREE_CODE (type) == UNION_TYPE
                 || TREE_CODE (type) == QUAL_UNION_TYPE)
                && TYPE_NAME (type) == decl
-               && !(use_gnu_debug_info_extensions && have_used_extensions)
+               && !use_gnu_debug_info_extensions
                && !TREE_ASM_WRITTEN (TYPE_NAME (type))
                /* Distinguish the implicit typedefs of C++
                   from explicit ones that might be found in C.  */
@@ -2527,11 +2669,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
 
            dbxout_begin_complex_stabs ();
 
-           /* Output leading class/struct qualifiers.
-              ??? why not set have_used_extensions here ... because
-              then the test of it below would always be true, I
-              guess.  But it's not clear to me why we shouldn't do
-              that always in extended mode.  */
+           /* Output leading class/struct qualifiers.  */
            if (use_gnu_debug_info_extensions)
              dbxout_class_name_qualifiers (decl);
 
@@ -2548,7 +2686,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
                   from explicit ones that might be found in C.  */
                && DECL_ARTIFICIAL (decl))
              {
-               if (use_gnu_debug_info_extensions && have_used_extensions)
+               if (use_gnu_debug_info_extensions)
                  {
                    stabstr_C ('T');
                    TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1;
@@ -2613,10 +2751,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       gcc_unreachable ();
 
     case RESULT_DECL:
-      /* Named return value, treat like a VAR_DECL.  */
     case VAR_DECL:
-      if (! DECL_RTL_SET_P (decl))
-       DBXOUT_DECR_NESTING_AND_RETURN (0);
       /* Don't mention a variable that is external.
         Let the file that defines it describe it.  */
       if (DECL_EXTERNAL (decl))
@@ -2631,7 +2766,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
          && host_integerp (DECL_INITIAL (decl), 0)
          && ! TREE_ASM_WRITTEN (decl)
          && (DECL_CONTEXT (decl) == NULL_TREE
-             || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK)
+             || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
+             || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
          && TREE_PUBLIC (decl) == 0)
        {
          /* The sun4 assembler does not grok this.  */
@@ -2642,8 +2778,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
              HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
 
              dbxout_begin_complex_stabs ();
-             stabstr_I (DECL_NAME (decl));
-             stabstr_S (":c=i");
+             dbxout_symbol_name (decl, NULL, 'c');
+             stabstr_S ("=i");
              stabstr_D (ival);
              dbxout_finish_complex_stabs (0, N_LSYM, 0, 0, 0);
              DBXOUT_DECR_NESTING;
@@ -2654,13 +2790,17 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
        }
       /* else it is something we handle like a normal variable.  */
 
-      SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
+      decl_rtl = dbxout_expand_expr (decl);
+      if (!decl_rtl)
+       DBXOUT_DECR_NESTING_AND_RETURN (0);
+
+      decl_rtl = eliminate_regs (decl_rtl, 0, NULL_RTX);
 #ifdef LEAF_REG_REMAP
       if (current_function_uses_only_leaf_regs)
-       leaf_renumber_regs_insn (DECL_RTL (decl));
+       leaf_renumber_regs_insn (decl_rtl);
 #endif
 
-      result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+      result = dbxout_symbol_location (decl, type, 0, decl_rtl);
       break;
 
     default:
@@ -2784,7 +2924,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
            {
              /* Ultrix `as' seems to need this.  */
 #ifdef DBX_STATIC_STAB_DATA_SECTION
-             data_section ();
+             switch_to_section (data_section);
 #endif
              code = N_STSYM;
            }
@@ -3218,6 +3358,8 @@ dbxout_args (tree args)
     }
 }
 \f
+#if defined (DBX_DEBUGGING_INFO)
+
 /* 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.  */
@@ -3225,15 +3367,11 @@ static void
 dbx_output_lbrac (const char *label,
                  const char *begin_label ATTRIBUTE_UNUSED)
 {
-#ifdef DBX_OUTPUT_LBRAC
-  DBX_OUTPUT_LBRAC (asm_out_file, label);
-#else
   dbxout_begin_stabn (N_LBRAC);
   if (DBX_BLOCKS_FUNCTION_RELATIVE)
     dbxout_stab_value_label_diff (label, begin_label);
   else
     dbxout_stab_value_label (label);
-#endif
 }
 
 /* Subroutine of dbxout_block.  Emit an N_RBRAC stab referencing LABEL.
@@ -3243,15 +3381,11 @@ static void
 dbx_output_rbrac (const char *label,
                  const char *begin_label ATTRIBUTE_UNUSED)
 {
-#ifdef DBX_OUTPUT_RBRAC
-  DBX_OUTPUT_RBRAC (asm_out_file, label);
-#else
   dbxout_begin_stabn (N_RBRAC);
   if (DBX_BLOCKS_FUNCTION_RELATIVE)
     dbxout_stab_value_label_diff (label, begin_label);
   else
     dbxout_stab_value_label (label);
-#endif
 }
 
 /* Output everything about a symbol block (a BLOCK node
@@ -3274,8 +3408,9 @@ dbx_output_rbrac (const char *label,
 static void
 dbxout_block (tree block, int depth, tree args)
 {
-  const char *begin_label
-    = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+  char begin_label[20];
+  /* Reference current function start using LFBB.  */
+  ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
 
   while (block)
     {
@@ -3304,7 +3439,7 @@ dbxout_block (tree block, int depth, tree args)
 
              if (depth == 0)
                /* The outermost block doesn't get LBB labels; use
-                  the function symbol.  */
+                  the LFBB local symbol emitted by dbxout_begin_prologue.  */
                scope_start = begin_label;
              else
                {
@@ -3355,7 +3490,6 @@ dbxout_block (tree block, int depth, tree args)
    Usually this follows the function's code,
    but on some systems, it comes before.  */
 
-#if defined (DBX_DEBUGGING_INFO)
 static void
 dbxout_begin_function (tree decl)
 {