OSDN Git Service

2009-04-05 Daniel Kraft <d@domob.eu>
[pf3gnuchains/gcc-fork.git] / gcc / dbxout.c
index cb7df88..babba15 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,
 /* 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, 2008
+   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
 
 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
 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
 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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* Output dbx-format symbol table data.
 
 
 /* Output dbx-format symbol table data.
@@ -322,11 +322,13 @@ static void dbxout_type_methods (tree);
 static void dbxout_range_type (tree);
 static void dbxout_type (tree, int);
 static bool print_int_cst_bounds_in_octal_p (tree);
 static void dbxout_range_type (tree);
 static void dbxout_type (tree, int);
 static bool print_int_cst_bounds_in_octal_p (tree);
+static bool is_fortran (void);
 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_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_common_name (tree, const char *, STAB_CODE_TYPE);
+static const char *dbxout_common_check (tree, int *);
 static void dbxout_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 static void dbxout_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
@@ -353,7 +355,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_end_source_file,
   dbxout_begin_block,
   dbxout_end_block,
   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 */
   dbxout_source_line,                   /* source_line */
   dbxout_begin_prologue,                /* begin_prologue */
   debug_nothing_int_charstar,           /* end_prologue */
@@ -367,7 +369,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_function_decl,
   dbxout_global_decl,                   /* global_decl */
   dbxout_type_decl,                     /* type_decl */
   dbxout_function_decl,
   dbxout_global_decl,                   /* global_decl */
   dbxout_type_decl,                     /* type_decl */
-  debug_nothing_tree_tree,               /* imported_module_or_decl */
+  debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
   debug_nothing_tree,                   /* deferred_inline_function */
   debug_nothing_tree,                   /* outlining_inline_function */
   debug_nothing_rtx,                    /* label */
   debug_nothing_tree,                   /* deferred_inline_function */
   debug_nothing_tree,                   /* outlining_inline_function */
   debug_nothing_rtx,                    /* label */
@@ -389,7 +391,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   dbxout_end_source_file,
   xcoffout_begin_block,
   xcoffout_end_block,
   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 */
   xcoffout_source_line,
   xcoffout_begin_prologue,              /* begin_prologue */
   debug_nothing_int_charstar,           /* end_prologue */
@@ -399,7 +401,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   debug_nothing_tree,                   /* function_decl */
   dbxout_global_decl,                   /* global_decl */
   dbxout_type_decl,                     /* type_decl */
   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_tree_tree_bool,    /* imported_module_or_decl */
   debug_nothing_tree,                   /* deferred_inline_function */
   debug_nothing_tree,                   /* outlining_inline_function */
   debug_nothing_rtx,                    /* label */
   debug_nothing_tree,                   /* deferred_inline_function */
   debug_nothing_tree,                   /* outlining_inline_function */
   debug_nothing_rtx,                    /* label */
@@ -914,7 +916,6 @@ dbxout_function_end (tree decl)
      labels.  */
   ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno);
   targetm.asm_out.internal_label (asm_out_file, "Lscope", scope_labelno);
      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
 
   /* 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
@@ -927,27 +928,23 @@ dbxout_function_end (tree decl)
 
   /* By convention, GCC will mark the end of a function with an N_FUN
      symbol and an empty string.  */
 
   /* 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
   if (flag_reorder_blocks_and_partition)
     {
       dbxout_begin_empty_stabs (N_FUN);
   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_stab_value_label_diff (crtl->subsections.hot_section_end_label, 
+                                   crtl->subsections.hot_section_label);
       dbxout_begin_empty_stabs (N_FUN);
       dbxout_begin_empty_stabs (N_FUN);
-      dbxout_stab_value_label_diff (cfun->cold_section_end_label, 
-                                   cfun->cold_section_label);
+      dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label, 
+                                   crtl->subsections.cold_section_label);
     }
   else
     {
     }
   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_begin_empty_stabs (N_FUN);
-      dbxout_stab_value_label_diff (lscope_label_name,
-                                   XSTR (XEXP (DECL_RTL (current_function_decl), 
-                                               0), 0));
+      dbxout_stab_value_label_diff (lscope_label_name, begin_label);
     }
     }
-                               
-#endif
 
   if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols)
     dbxout_stabd (N_ENSYM, 0);
 
   if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols)
     dbxout_stabd (N_ENSYM, 0);
@@ -966,7 +963,7 @@ get_lang_number (void)
     return N_SO_CC;
   else if (strcmp (language_string, "GNU F77") == 0)
     return N_SO_FORTRAN;
     return N_SO_CC;
   else if (strcmp (language_string, "GNU F77") == 0)
     return N_SO_FORTRAN;
-  else if (strcmp (language_string, "GNU F95") == 0)
+  else if (strcmp (language_string, "GNU Fortran") == 0)
     return N_SO_FORTRAN90; /* CHECKME */
   else if (strcmp (language_string, "GNU Pascal") == 0)
     return N_SO_PASCAL;
     return N_SO_FORTRAN90; /* CHECKME */
   else if (strcmp (language_string, "GNU Pascal") == 0)
     return N_SO_PASCAL;
@@ -979,6 +976,14 @@ get_lang_number (void)
 
 }
 
 
 }
 
+static bool
+is_fortran (void)
+{
+   unsigned int lang = get_lang_number ();
+
+   return (lang == N_SO_FORTRAN) || (lang == N_SO_FORTRAN90);
+}
+
 /* At the beginning of compilation, start writing the symbol table.
    Initialize `typevec' and output the standard data types of C.  */
 
 /* At the beginning of compilation, start writing the symbol table.
    Initialize `typevec' and output the standard data types of C.  */
 
@@ -988,9 +993,10 @@ dbxout_init (const char *input_file_name)
   char ltext_label_name[100];
   bool used_ltext_label_name = false;
   tree syms = lang_hooks.decls.getdecls ();
   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_len = 100;
-  typevec = ggc_calloc (typevec_len, sizeof typevec[0]);
+  typevec = GGC_CNEWVEC (struct typeinfo, typevec_len);
 
   /* stabstr_ob contains one string, which will be just fine with
      1-byte alignment.  */
 
   /* stabstr_ob contains one string, which will be just fine with
      1-byte alignment.  */
@@ -1013,6 +1019,7 @@ dbxout_init (const char *input_file_name)
            cwd = "/";
          else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1]))
            cwd = concat (cwd, "/", NULL);
            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);
        }
 #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
       DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd);
@@ -1023,10 +1030,11 @@ dbxout_init (const char *input_file_name)
 #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
     }
 
 #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
     }
 
+  mapped_name = remap_debug_filename (input_file_name);
 #ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
 #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
 #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
   dbxout_stab_value_label (ltext_label_name);
   used_ltext_label_name = true;
 #endif
@@ -1049,7 +1057,7 @@ dbxout_init (const char *input_file_name)
   next_type_number = 1;
 
 #ifdef DBX_USE_BINCL
   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;
   current_file->next = NULL;
   current_file->file_number = 0;
   current_file->next_type_number = 1;
@@ -1158,7 +1166,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
                          const char *filename ATTRIBUTE_UNUSED)
 {
 #ifdef DBX_USE_BINCL
                          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;
 
   n->next = current_file;
   n->next_type_number = 1;
@@ -1168,7 +1176,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
   n->prev = NULL;
   current_file->prev = n;
   n->bincl_status = BINCL_PENDING;
   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
   pending_bincls = 1;
   current_file = n;
 #endif
@@ -1217,6 +1225,9 @@ dbxout_handle_pch (unsigned at_end)
 }
 
 #if defined (DBX_DEBUGGING_INFO)
 }
 
 #if defined (DBX_DEBUGGING_INFO)
+
+static void dbxout_block (tree, int, tree);
+
 /* Output debugging info to FILE to switch to sourcefile FILENAME.  */
 
 static void
 /* Output debugging info to FILE to switch to sourcefile FILENAME.  */
 
 static void
@@ -1234,13 +1245,14 @@ dbxout_source_file (const char *filename)
       if (current_function_decl == NULL_TREE)
        switch_to_section (text_section);
 
       if (current_function_decl == NULL_TREE)
        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;
     }
 }
 
       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)
 
 static void
 dbxout_begin_prologue (unsigned int lineno, const char *filename)
@@ -1251,7 +1263,14 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename)
       && !flag_debug_only_used_symbols)
     dbxout_stabd (N_BNSYM, 0);
 
       && !flag_debug_only_used_symbols)
     dbxout_stabd (N_BNSYM, 0);
 
+  /* pre-increment the scope counter */
+  scope_labelno++;
+
   dbxout_source_line (lineno, filename);
   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
 }
 
 /* Output a line number symbol entry for source file FILENAME and line
@@ -1267,11 +1286,12 @@ dbxout_source_line (unsigned int lineno, const char *filename)
 #else
   if (DBX_LINES_FUNCTION_RELATIVE)
     {
 #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);
       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,
       dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter,
-                                            XSTR (begin_label, 0));
-
+                                            begin_label);
     }
   else
     dbxout_stabd (N_SLINE, lineno);
     }
   else
     dbxout_stabd (N_SLINE, lineno);
@@ -1689,8 +1709,7 @@ dbxout_type (tree type, int full)
 
       if (next_type_number == typevec_len)
        {
 
       if (next_type_number == typevec_len)
        {
-         typevec
-           = ggc_realloc (typevec, (typevec_len * 2 * sizeof typevec[0]));
+         typevec = GGC_RESIZEVEC (struct typeinfo, typevec, typevec_len * 2);
          memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]);
          typevec_len *= 2;
        }
          memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]);
          typevec_len *= 2;
        }
@@ -1902,6 +1921,7 @@ dbxout_type (tree type, int full)
       break;
 
     case REAL_TYPE:
       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');
       /* This used to say `r1' and we used to take care
         to make sure that `int' was type number 1.  */
       stabstr_C ('r');
@@ -1911,23 +1931,6 @@ dbxout_type (tree type, int full)
       stabstr_S (";0;");
       break;
 
       stabstr_S (";0;");
       break;
 
-    case CHAR_TYPE:
-      if (use_gnu_debug_info_extensions)
-       {
-         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)
        {
     case BOOLEAN_TYPE:
       if (use_gnu_debug_info_extensions)
        {
@@ -2036,7 +2039,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");
               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
              {
              dbxout_type_name (type);
            else
              {
@@ -2167,16 +2174,21 @@ dbxout_type (tree type, int full)
       stabstr_C ('e');
       for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
        {
       stabstr_C ('e');
       for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
        {
+          tree value = TREE_VALUE (tem);
+
          stabstr_I (TREE_PURPOSE (tem));
          stabstr_C (':');
 
          stabstr_I (TREE_PURPOSE (tem));
          stabstr_C (':');
 
-         if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0)
-           stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem)));
-         else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1
-                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)
-           stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem)));
+          if (TREE_CODE (value) == CONST_DECL)
+            value = DECL_INITIAL (value);
+
+         if (TREE_INT_CST_HIGH (value) == 0)
+           stabstr_D (TREE_INT_CST_LOW (value));
+         else if (TREE_INT_CST_HIGH (value) == -1
+                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
+           stabstr_D (TREE_INT_CST_LOW (value));
          else
          else
-           stabstr_O (TREE_VALUE (tem));
+           stabstr_O (value);
 
          stabstr_C (',');
          if (TREE_CHAIN (tem) != 0)
 
          stabstr_C (',');
          if (TREE_CHAIN (tem) != 0)
@@ -2326,7 +2338,7 @@ 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
 \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
+   haven'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
    be able to represent it in stabs anyway.  Returns NULL on failure.  */
 
 static rtx
@@ -2335,6 +2347,15 @@ dbxout_expand_expr (tree expr)
   switch (TREE_CODE (expr))
     {
     case VAR_DECL:
   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));
     case PARM_DECL:
       if (DECL_HAS_VALUE_EXPR_P (expr))
        return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
@@ -2381,6 +2402,83 @@ dbxout_expand_expr (tree expr)
     }
 }
 
     }
 }
 
+/* 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 = (tree) *slot;
+  VEC(tree, heap) **types_p = (VEC(tree, heap) **) 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.
 /* 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.
@@ -2406,7 +2504,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
 
   /* If we are to generate only the symbols actually used then such
      symbol nodes are flagged with TREE_USED.  Ignore any that
 
   /* If we are to generate only the symbols actually used then such
      symbol nodes are flagged with TREE_USED.  Ignore any that
-     aren't flaged as TREE_USED.  */
+     aren't flagged as TREE_USED.  */
 
   if (flag_debug_only_used_symbols
       && (!TREE_USED (decl)
 
   if (flag_debug_only_used_symbols
       && (!TREE_USED (decl)
@@ -2494,6 +2592,9 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
          || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF)
        break;
 
          || 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");
       dbxout_begin_complex_stabs ();
       stabstr_I (DECL_ASSEMBLER_NAME (decl));
       stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f");
@@ -2782,8 +2883,15 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
     {
       if (TREE_PUBLIC (decl))
        {
     {
       if (TREE_PUBLIC (decl))
        {
+         int offs;
          letter = 'G';
          code = N_GSYM;
          letter = 'G';
          code = N_GSYM;
+         if (NULL != dbxout_common_check (decl, &offs))
+           {
+             letter = 'V';
+             addr = 0;
+             number = offs;
+           }
        }
       else
        {
        }
       else
        {
@@ -2829,7 +2937,17 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
          if (DECL_INITIAL (decl) == 0
              || (!strcmp (lang_hooks.name, "GNU C++")
                  && DECL_INITIAL (decl) == error_mark_node))
          if (DECL_INITIAL (decl) == 0
              || (!strcmp (lang_hooks.name, "GNU C++")
                  && DECL_INITIAL (decl) == error_mark_node))
-           code = N_LCSYM;
+           {
+             int offs;
+             code = N_LCSYM;
+             if (NULL != dbxout_common_check (decl, &offs))
+               {
+                 addr = 0;
+                 number = offs;
+                 letter = 'V';
+                 code = N_GSYM;
+               }
+           }
          else if (DECL_IN_TEXT_SECTION (decl))
            /* This is not quite right, but it's the closest
               of all the codes that Unix defines.  */
          else if (DECL_IN_TEXT_SECTION (decl))
            /* This is not quite right, but it's the closest
               of all the codes that Unix defines.  */
@@ -2918,9 +3036,17 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
         variable, thereby avoiding the need for a register.  In such
         cases we're forced to lie to debuggers and tell them that
         this variable was itself `static'.  */
         variable, thereby avoiding the need for a register.  In such
         cases we're forced to lie to debuggers and tell them that
         this variable was itself `static'.  */
+      int offs;
       code = N_LCSYM;
       letter = 'V';
       code = N_LCSYM;
       letter = 'V';
-      addr = XEXP (XEXP (home, 0), 0);
+      if (NULL == dbxout_common_check (decl, &offs))
+        addr = XEXP (XEXP (home, 0), 0);
+      else
+        {
+         addr = 0;
+         number = offs;
+         code = N_GSYM;
+       }
     }
   else if (GET_CODE (home) == CONCAT)
     {
     }
   else if (GET_CODE (home) == CONCAT)
     {
@@ -3005,6 +3131,115 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter)
     stabstr_C (letter);
 }
 
     stabstr_C (letter);
 }
 
+
+/* Output the common block name for DECL in a stabs.
+
+   Symbols in global common (.comm) get wrapped with an N_BCOMM/N_ECOMM pair
+   around each group of symbols in the same .comm area.  The N_GSYM stabs
+   that are emitted only contain the offset in the common area.  This routine
+   emits the N_BCOMM and N_ECOMM stabs.  */
+
+static void
+dbxout_common_name (tree decl, const char *name, STAB_CODE_TYPE op)
+{
+  dbxout_begin_complex_stabs ();
+  stabstr_S (name);
+  dbxout_finish_complex_stabs (decl, op, NULL_RTX, NULL, 0);
+}
+
+/* Check decl to determine whether it is a VAR_DECL destined for storage in a
+   common area.  If it is, the return value will be a non-null string giving
+   the name of the common storage block it will go into.  If non-null, the
+   value is the offset into the common block for that symbol's storage.  */
+
+static const char *
+dbxout_common_check (tree decl, int *value)
+{
+  rtx home;
+  rtx sym_addr;
+  const char *name = NULL;
+  
+  /* If the decl isn't a VAR_DECL, or if it isn't public or static, or if
+     it does not have a value (the offset into the common area), or if it
+     is thread local (as opposed to global) then it isn't common, and shouldn't
+     be handled as such.
+     
+     ??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs
+     for thread-local symbols.  Can be handled via same mechanism as used
+     in dwarf2out.c.  */
+  if (TREE_CODE (decl) != VAR_DECL
+      || !TREE_PUBLIC(decl)
+      || !TREE_STATIC(decl)
+      || !DECL_HAS_VALUE_EXPR_P(decl)
+      || DECL_THREAD_LOCAL_P (decl)
+      || !is_fortran ())
+    return NULL;
+
+  home = DECL_RTL (decl); 
+  if (home == NULL_RTX || GET_CODE (home) != MEM)
+    return NULL;
+
+  sym_addr = dbxout_expand_expr (DECL_VALUE_EXPR (decl));
+  if (sym_addr == NULL_RTX || GET_CODE (sym_addr) != MEM)
+    return NULL;
+
+  sym_addr = XEXP (sym_addr, 0);
+  if (GET_CODE (sym_addr) == CONST)
+    sym_addr = XEXP (sym_addr, 0);
+  if ((GET_CODE (sym_addr) == SYMBOL_REF || GET_CODE (sym_addr) == PLUS)
+      && DECL_INITIAL (decl) == 0)
+    {
+
+      /* We have a sym that will go into a common area, meaning that it
+         will get storage reserved with a .comm/.lcomm assembler pseudo-op.
+
+         Determine name of common area this symbol will be an offset into,
+         and offset into that area.  Also retrieve the decl for the area
+         that the symbol is offset into.  */
+      tree cdecl = NULL;
+
+      switch (GET_CODE (sym_addr))
+        {
+        case PLUS:
+          if (GET_CODE (XEXP (sym_addr, 0)) == CONST_INT)
+            {
+              name =
+                targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 1), 0));
+              *value = INTVAL (XEXP (sym_addr, 0));
+              cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1));
+            }
+          else
+            {
+              name =
+                targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 0), 0));
+              *value = INTVAL (XEXP (sym_addr, 1));
+              cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0));
+            }
+          break;
+
+        case SYMBOL_REF:
+          name = targetm.strip_name_encoding(XSTR (sym_addr, 0));
+          *value = 0;
+          cdecl = SYMBOL_REF_DECL (sym_addr);
+          break;
+
+        default:
+          error ("common symbol debug info is not structured as "
+                 "symbol+offset");
+        }
+
+      /* Check area common symbol is offset into.  If this is not public, then
+         it is not a symbol in a common block.  It must be a .lcomm symbol, not
+         a .comm symbol.  */
+      if (cdecl == NULL || !TREE_PUBLIC(cdecl))
+        name = NULL;
+    }
+  else
+    name = NULL;
+
+  return name;
+}
+
 /* Output definitions of all the decls in a chain. Return nonzero if
    anything was output */
 
 /* Output definitions of all the decls in a chain. Return nonzero if
    anything was output */
 
@@ -3012,11 +3247,38 @@ int
 dbxout_syms (tree syms)
 {
   int result = 0;
 dbxout_syms (tree syms)
 {
   int result = 0;
+  const char *comm_prev = NULL;
+  tree syms_prev = NULL;
+
   while (syms)
     {
   while (syms)
     {
+      int temp, copen, cclos;
+      const char *comm_new;
+
+      /* Check for common symbol, and then progression into a new/different
+         block of common symbols.  Emit closing/opening common bracket if
+         necessary.  */
+      comm_new = dbxout_common_check (syms, &temp);
+      copen = comm_new != NULL
+              && (comm_prev == NULL || strcmp (comm_new, comm_prev));
+      cclos = comm_prev != NULL
+              && (comm_new == NULL || strcmp (comm_new, comm_prev));
+      if (cclos)
+        dbxout_common_name (syms_prev, comm_prev, N_ECOMM);
+      if (copen)
+        {
+          dbxout_common_name (syms, comm_new, N_BCOMM);
+          syms_prev = syms;
+        }
+      comm_prev = comm_new;
+
       result += dbxout_symbol (syms, 1);
       syms = TREE_CHAIN (syms);
     }
       result += dbxout_symbol (syms, 1);
       syms = TREE_CHAIN (syms);
     }
+
+  if (comm_prev != NULL)
+    dbxout_common_name (syms_prev, comm_prev, N_ECOMM);
+
   return result;
 }
 \f
   return result;
 }
 \f
@@ -3114,6 +3376,8 @@ dbxout_parms (tree parms)
               was passed.  */
            if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
              best_rtl = DECL_RTL (parms);
               was passed.  */
            if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
              best_rtl = DECL_RTL (parms);
+           else if (GET_CODE (DECL_INCOMING_RTL (parms)) == PARALLEL)
+             best_rtl = XEXP (XVECEXP (DECL_INCOMING_RTL (parms), 0, 0), 0);
            else
              best_rtl = DECL_INCOMING_RTL (parms);
 
            else
              best_rtl = DECL_INCOMING_RTL (parms);
 
@@ -3272,6 +3536,8 @@ dbxout_args (tree args)
     }
 }
 \f
     }
 }
 \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.  */
 /* 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.  */
@@ -3279,15 +3545,11 @@ static void
 dbx_output_lbrac (const char *label,
                  const char *begin_label ATTRIBUTE_UNUSED)
 {
 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);
   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.
 }
 
 /* Subroutine of dbxout_block.  Emit an N_RBRAC stab referencing LABEL.
@@ -3297,15 +3559,11 @@ static void
 dbx_output_rbrac (const char *label,
                  const char *begin_label ATTRIBUTE_UNUSED)
 {
 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);
   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
 }
 
 /* Output everything about a symbol block (a BLOCK node
@@ -3328,13 +3586,14 @@ dbx_output_rbrac (const char *label,
 static void
 dbxout_block (tree block, int depth, tree args)
 {
 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)
     {
       /* Ignore blocks never expanded or otherwise marked as real.  */
 
   while (block)
     {
       /* Ignore blocks never expanded or otherwise marked as real.  */
-      if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
+      if (TREE_ASM_WRITTEN (block))
        {
          int did_output;
          int blocknum = BLOCK_NUMBER (block);
        {
          int did_output;
          int blocknum = BLOCK_NUMBER (block);
@@ -3358,7 +3617,7 @@ dbxout_block (tree block, int depth, tree args)
 
              if (depth == 0)
                /* The outermost block doesn't get LBB labels; use
 
              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
                {
                scope_start = begin_label;
              else
                {
@@ -3366,20 +3625,6 @@ dbxout_block (tree block, int depth, tree args)
                  scope_start = buf;
                }
 
                  scope_start = buf;
                }
 
-             if (BLOCK_HANDLER_BLOCK (block))
-               {
-                 /* A catch block.  Must precede N_LBRAC.  */
-                 tree decl = BLOCK_VARS (block);
-                 while (decl)
-                   {
-                     dbxout_begin_complex_stabs ();
-                     stabstr_I (DECL_NAME (decl));
-                     stabstr_S (":C1");
-                     dbxout_finish_complex_stabs (0, N_CATCH, 0,
-                                                  scope_start, 0);
-                     decl = TREE_CHAIN (decl);
-                   }
-               }
              dbx_output_lbrac (scope_start, begin_label);
            }
 
              dbx_output_lbrac (scope_start, begin_label);
            }
 
@@ -3409,7 +3654,6 @@ dbxout_block (tree block, int depth, tree args)
    Usually this follows the function's code,
    but on some systems, it comes before.  */
 
    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)
 {
 static void
 dbxout_begin_function (tree decl)
 {