OSDN Git Service

* expr.c (move_block_from_reg): Try using an integral mov operation first.
[pf3gnuchains/gcc-fork.git] / gcc / dwarfout.c
index 1026f46..f91cccb 100644 (file)
@@ -1,8 +1,6 @@
-/* This file contains code written by Ron Guilmette (rfg@ncd.com) for
-   Network Computing Devices, August, September, October, November 1990.
-
-   Output Dwarf format symbol table information from the GNU C compiler.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+/* Output Dwarf format symbol table information from the GNU C compiler.
+   Copyright (C) 1992, 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices.
 
 This file is part of GNU CC.
 
@@ -18,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.  */
 
 #include "config.h"
 
@@ -34,10 +33,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "output.h"
 #include "defaults.h"
 
-#ifndef DWARF_VERSION
-#define DWARF_VERSION 1
-#endif
-
 /* #define NDEBUG 1 */
 #include "assert.h"
 
@@ -70,10 +65,8 @@ extern char *rindex ();
 /* Note that the implementation of C++ support herein is (as yet) unfinished.
    If you want to try to complete it, more power to you.  */
 
-#if defined(__GNUC__) && (NDEBUG == 1)
-#define inline static inline
-#else
-#define inline static
+#if !defined(__GNUC__) || (NDEBUG != 1)
+#define inline
 #endif
 
 /* How to start an assembler comment.  */
@@ -104,6 +97,21 @@ extern char *rindex ();
 
 #define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
 
+/* Define a macro which returns non-zero for a TYPE_DECL which was
+   implicitly generated for a tagged type.
+
+   Note that unlike the gcc front end (which generates a NULL named
+   TYPE_DECL node for each complete tagged type, each array type, and
+   each function type node created) the g++ front end generates a
+   _named_ TYPE_DECL node for each tagged type node created.
+   These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
+   generate a DW_TAG_typedef DIE for them.  */
+#define TYPE_DECL_IS_STUB(decl)                                \
+  (DECL_NAME (decl) == NULL                            \
+   || (DECL_ARTIFICIAL (decl)                          \
+       && is_tagged_type (TREE_TYPE (decl))            \
+       && decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
+
 extern int flag_traditional;
 extern char *version_string;
 extern char *language_string;
@@ -166,7 +174,7 @@ struct filename_entry {
 
 typedef struct filename_entry filename_entry;
 
-/* Pointer to an array of elements, each one having the structure above. */
+/* Pointer to an array of elements, each one having the structure above.  */
 
 static filename_entry *filename_table;
 
@@ -205,7 +213,7 @@ static char *last_filename;
 
 static unsigned next_block_number = 2;
 
-/* Counter to generate unique names for DIEs. */
+/* Counter to generate unique names for DIEs.  */
 
 static unsigned next_unused_dienum = 1;
 
@@ -291,13 +299,128 @@ static unsigned current_funcdef_number = 1;
 
 static tree dwarf_last_decl;
 
+/* A flag indicating that we are emitting the member declarations of a
+   class, so member functions and variables should not be entirely emitted.
+   This is a kludge to avoid passing a second argument to output_*_die.  */
+
+static int in_class;
+
 /* Forward declarations for functions defined in this file.  */
 
-static void output_type ();
-static void type_attribute ();
-static void output_decls_for_scope ();
-static void output_decl ();
-static unsigned lookup_filename ();
+static char *dwarf_tag_name            PROTO((unsigned));
+static char *dwarf_attr_name           PROTO((unsigned));
+static char *dwarf_stack_op_name       PROTO((unsigned));
+static char *dwarf_typemod_name                PROTO((unsigned));
+static char *dwarf_fmt_byte_name       PROTO((unsigned));
+static char *dwarf_fund_type_name      PROTO((unsigned));
+static tree decl_ultimate_origin       PROTO((tree));
+static tree block_ultimate_origin      PROTO((tree));
+static void output_unsigned_leb128     PROTO((unsigned long));
+static void output_signed_leb128       PROTO((long));
+static inline int is_body_block                PROTO((tree));
+static int fundamental_type_code       PROTO((tree));
+static tree root_type_1                        PROTO((tree, int));
+static tree root_type                  PROTO((tree));
+static void write_modifier_bytes_1     PROTO((tree, int, int, int));
+static void write_modifier_bytes       PROTO((tree, int, int));
+static inline int type_is_fundamental  PROTO((tree));
+static void equate_decl_number_to_die_number PROTO((tree));
+static inline void equate_type_number_to_die_number PROTO((tree));
+static void output_reg_number          PROTO((rtx));
+static void output_mem_loc_descriptor  PROTO((rtx));
+static void output_loc_descriptor      PROTO((rtx));
+static void output_bound_representation        PROTO((tree, unsigned, int));
+static void output_enumeral_list       PROTO((tree));
+static inline unsigned ceiling         PROTO((unsigned, unsigned));
+static inline tree field_type          PROTO((tree));
+static inline unsigned simple_type_align_in_bits PROTO((tree));
+static inline unsigned simple_type_size_in_bits  PROTO((tree));
+static unsigned field_byte_offset      PROTO((tree));
+static inline void sibling_attribute   PROTO((void));
+static void location_attribute         PROTO((rtx));
+static void data_member_location_attribute PROTO((tree));
+static void const_value_attribute      PROTO((rtx));
+static void location_or_const_value_attribute PROTO((tree));
+static inline void name_attribute      PROTO((char *));
+static inline void fund_type_attribute PROTO((unsigned));
+static void mod_fund_type_attribute    PROTO((tree, int, int));
+static inline void user_def_type_attribute PROTO((tree));
+static void mod_u_d_type_attribute     PROTO((tree, int, int));
+static inline void ordering_attribute  PROTO((unsigned));
+static void subscript_data_attribute   PROTO((tree));
+static void byte_size_attribute                PROTO((tree));
+static inline void bit_offset_attribute        PROTO((tree));
+static inline void bit_size_attribute  PROTO((tree));
+static inline void element_list_attribute PROTO((tree));
+static inline void stmt_list_attribute PROTO((char *));
+static inline void low_pc_attribute    PROTO((char *));
+static inline void high_pc_attribute   PROTO((char *));
+static inline void body_begin_attribute        PROTO((char *));
+static inline void body_end_attribute  PROTO((char *));
+static inline void langauge_attribute  PROTO((unsigned));
+static inline void member_attribute    PROTO((tree));
+static inline void string_length_attribute PROTO((tree));
+static inline void comp_dir_attribute  PROTO((char *));
+static inline void sf_names_attribute  PROTO((char *));
+static inline void src_info_attribute  PROTO((char *));
+static inline void mac_info_attribute  PROTO((char *));
+static inline void prototyped_attribute        PROTO((tree));
+static inline void producer_attribute  PROTO((char *));
+static inline void inline_attribute    PROTO((tree));
+static inline void containing_type_attribute PROTO((tree));
+static inline void abstract_origin_attribute PROTO((tree));
+static inline void src_coords_attribute PROTO((unsigned, unsigned));
+static inline void pure_or_virtual_attribute PROTO((tree));
+static void name_and_src_coords_attributes PROTO((tree));
+static void type_attribute             PROTO((tree, int, int));
+static char *type_tag                  PROTO((tree));
+static inline void dienum_push         PROTO((void));
+static inline void dienum_pop          PROTO((void));
+static inline tree member_declared_type PROTO((tree));
+static char *function_start_label      PROTO((tree));
+static void output_array_type_die      PROTO((void *));
+static void output_set_type_die                PROTO((void *));
+static void output_entry_point_die     PROTO((void *));
+static void output_inlined_enumeration_type_die PROTO((void *));
+static void output_inlined_structure_type_die PROTO((void *));
+static void output_inlined_union_type_die PROTO((void *));
+static void output_enumeration_type_die        PROTO((void *));
+static void output_formal_parameter_die        PROTO((void *));
+static void output_global_subroutine_die PROTO((void *));
+static void output_global_variable_die PROTO((void *));
+static void output_label_die           PROTO((void *));
+static void output_lexical_block_die   PROTO((void *));
+static void output_inlined_subroutine_die PROTO((void *));
+static void output_local_variable_die  PROTO((void *));
+static void output_member_die          PROTO((void *));
+static void output_pointer_type_die    PROTO((void *));
+static void output_reference_type_die  PROTO((void *));
+static void output_ptr_to_mbr_type_die PROTO((void *));
+static void output_compile_unit_die    PROTO((void *));
+static void output_string_type_die     PROTO((void *));
+static void output_structure_type_die  PROTO((void *));
+static void output_local_subroutine_die PROTO((void *));
+static void output_subroutine_type_die PROTO((void *));
+static void output_typedef_die         PROTO((void *));
+static void output_union_type_die      PROTO((void *));
+static void output_unspecified_parameters_die PROTO((void *));
+static void output_padded_null_die     PROTO((void *));
+static void output_die                 PROTO((void (*) (), void *));
+static void end_sibling_chain          PROTO((void));
+static void output_formal_types                PROTO((tree));
+static void pend_type                  PROTO((tree));
+static inline int type_of_for_scope    PROTO((tree, tree));
+static void output_pending_types_for_scope PROTO((tree));
+static void output_type                        PROTO((tree, tree));
+static void output_tagged_type_instantiation PROTO((tree));
+static void output_block               PROTO((tree, int));
+static void output_decls_for_scope     PROTO((tree, int));
+static void output_decl                        PROTO((tree, tree));
+static void shuffle_filename_entry     PROTO((filename_entry *));
+static void geneate_new_sfname_entry   PROTO((void));
+static unsigned lookup_filename                PROTO((char *));
+static void generate_srcinfo_entry     PROTO((unsigned, unsigned));
+static void generate_macinfo_entry     PROTO((char *, char *));
 \f
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
@@ -346,7 +469,7 @@ static unsigned lookup_filename ();
    section name must be enclosed in double quotes.  (See sparcv4.h.)  */
 
 #ifndef PUSHSECTION_FORMAT
-#define PUSHSECTION_FORMAT     "%s\t%s\n"
+#define PUSHSECTION_FORMAT     "\t%s\t%s\n"
 #endif
 
 #ifndef DEBUG_SECTION
@@ -561,10 +684,7 @@ static unsigned lookup_filename ();
    output operations.
 
    If necessary, these may be overridden from within your tm.h file,
-   but typically, you shouldn't need to override these.  One known
-   exception is ASM_OUTPUT_DEF which has to be different for stock
-   sparc/svr4 assemblers.
-*/
+   but typically, you shouldn't need to override these.  */
 
 #ifndef ASM_OUTPUT_PUSH_SECTION
 #define ASM_OUTPUT_PUSH_SECTION(FILE, SECTION) \
@@ -578,16 +698,9 @@ static unsigned lookup_filename ();
 
 #ifndef ASM_OUTPUT_SOURCE_FILENAME
 #define ASM_OUTPUT_SOURCE_FILENAME(FILE,NAME) \
-  fprintf ((FILE), "\t%s\t\"%s\"\n", FILE_ASM_OP, NAME)
-#endif
-
-#ifndef ASM_OUTPUT_DEF
-#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2)                             \
- do {  fprintf ((FILE), "\t%s\t", SET_ASM_OP);                         \
-       assemble_name (FILE, LABEL1);                                   \
-       fprintf (FILE, ",");                                            \
-       assemble_name (FILE, LABEL2);                                   \
-       fprintf (FILE, "\n");                                           \
+  do { fprintf (FILE, "\t%s\t", FILE_ASM_OP);                          \
+       output_quoted_string (FILE, NAME);                              \
+       fputc ('\n', FILE);                                             \
   } while (0)
 #endif
 
@@ -616,7 +729,7 @@ static unsigned lookup_filename ();
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x",                                     \
                     UNALIGNED_SHORT_ASM_OP, (unsigned) TAG);           \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_tag_name (TAG));        \
     fputc ('\n', (FILE));                                              \
@@ -628,7 +741,7 @@ static unsigned lookup_filename ();
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x",                                     \
                     UNALIGNED_SHORT_ASM_OP, (unsigned) ATTR);          \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_attr_name (ATTR));      \
     fputc ('\n', (FILE));                                              \
@@ -639,7 +752,7 @@ static unsigned lookup_filename ();
 #define ASM_OUTPUT_DWARF_STACK_OP(FILE,OP)                             \
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) OP);                \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_stack_op_name (OP));    \
     fputc ('\n', (FILE));                                              \
@@ -651,7 +764,7 @@ static unsigned lookup_filename ();
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x",                                     \
                     UNALIGNED_SHORT_ASM_OP, (unsigned) FT);            \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_fund_type_name (FT));   \
     fputc ('\n', (FILE));                                              \
@@ -662,7 +775,7 @@ static unsigned lookup_filename ();
 #define ASM_OUTPUT_DWARF_FMT_BYTE(FILE,FMT)                            \
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) FMT);       \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_fmt_byte_name (FMT));   \
     fputc ('\n', (FILE));                                              \
@@ -673,7 +786,7 @@ static unsigned lookup_filename ();
 #define ASM_OUTPUT_DWARF_TYPE_MODIFIER(FILE,MOD)                       \
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) MOD);       \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_typemod_name (MOD));    \
     fputc ('\n', (FILE));                                              \
@@ -743,16 +856,6 @@ static unsigned lookup_filename ();
 \f
 /************************ general utility functions **************************/
 
-inline char *
-xstrdup (s)
-     register char *s;
-{
-  register char *p = (char *) xmalloc (strlen (s) + 1);
-
-  strcpy (p, s);
-  return p;
-}
-
 inline int
 is_pseudo_reg (rtl)
      register rtx rtl;
@@ -762,6 +865,26 @@ is_pseudo_reg (rtl)
              && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
 }
 
+inline tree
+type_main_variant (type)
+     register tree type;
+{
+  type = TYPE_MAIN_VARIANT (type);
+
+  /* There really should be only one main variant among any group of variants
+     of a given type (and all of the MAIN_VARIANT values for all members of
+     the group should point to that one type) but sometimes the C front-end
+     messes this up for array types, so we work around that bug here.  */
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      while (type != TYPE_MAIN_VARIANT (type))
+        type = TYPE_MAIN_VARIANT (type);
+    }
+
+  return type;
+}
+
 /* Return non-zero if the given type node represents a tagged type.  */
 
 inline int
@@ -951,6 +1074,7 @@ dwarf_fmt_byte_name (fmt)
     default:           return "FMT_<unknown>";
     }
 }
+
 static char *
 dwarf_fund_type_name (ft)
      register unsigned ft;
@@ -997,7 +1121,7 @@ dwarf_fund_type_name (ft)
     case FT_unsigned_int32:    return "FT_unsigned_int32";
     case FT_int64:             return "FT_int64";
     case FT_signed_int64:      return "FT_signed_int64";
-    case FT_unsigned_int64:    return "FT_signed_int64";
+    case FT_unsigned_int64:    return "FT_unsigned_int64";
 
     case FT_real32:            return "FT_real32";
     case FT_real64:            return "FT_real64";
@@ -1068,6 +1192,27 @@ block_ultimate_origin (block)
     }
 }
 
+/* Get the class to which DECL belongs, if any.  In g++, the DECL_CONTEXT
+   of a virtual function may refer to a base class, so we check the 'this'
+   parameter.  */
+
+static tree
+decl_class_context (decl)
+     tree decl;
+{
+  tree context = NULL_TREE;
+  if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
+    context = DECL_CONTEXT (decl);
+  else
+    context = TYPE_MAIN_VARIANT
+      (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
+
+  if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
+    context = NULL_TREE;
+
+  return context;
+}
+
 static void
 output_unsigned_leb128 (value)
      register unsigned long value;
@@ -1082,7 +1227,7 @@ output_unsigned_leb128 (value)
       if (value != 0)  /* more bytes to follow */
        byte |= 0x80;
       fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
-      if (flag_verbose_asm && value == 0)
+      if (flag_debug_asm && value == 0)
        fprintf (asm_out_file, "\t%s ULEB128 number - value = %u",
                 ASM_COMMENT_START, orig_value);
       fputc ('\n', asm_out_file);
@@ -1114,7 +1259,7 @@ output_signed_leb128 (value)
          more = 1;
        }
       fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
-      if (flag_verbose_asm && more == 0)
+      if (flag_debug_asm && more == 0)
        fprintf (asm_out_file, "\t%s SLEB128 number - value = %d",
                 ASM_COMMENT_START, orig_value);
       fputc ('\n', asm_out_file);
@@ -1136,7 +1281,7 @@ output_signed_leb128 (value)
    FUNCTION_DECL node.
 */
 
-inline int
+static inline int
 is_body_block (stmt)
      register tree stmt;
 {
@@ -1304,10 +1449,14 @@ fundamental_type_code (type)
    qualifiers.  */
 
 static tree
-root_type (type)
+root_type_1 (type, count)
      register tree type;
+     register int count;
 {
-  if (TREE_CODE (type) == ERROR_MARK)
+  /* Give up after searching 1000 levels, in case this is a recursive
+     pointer type.  Such types are possible in Ada, but it is not possible
+     to represent them in DWARF1 debug info.  */
+  if (count > 1000)
     return error_mark_node;
 
   switch (TREE_CODE (type))
@@ -1317,25 +1466,42 @@ root_type (type)
 
       case POINTER_TYPE:
       case REFERENCE_TYPE:
-       return TYPE_MAIN_VARIANT (root_type (TREE_TYPE (type)));
+       return root_type_1 (TREE_TYPE (type), count+1);
 
       default:
-       return TYPE_MAIN_VARIANT (type);
+       return type;
     }
 }
 
+static tree
+root_type (type)
+     register tree type;
+{
+  type = root_type_1 (type, 0);
+  if (type != error_mark_node)
+    type = type_main_variant (type);
+  return type;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, write out a sequence
    of zero or more Dwarf "type-modifier" bytes applicable to the type. */
 
 static void
-write_modifier_bytes (type, decl_const, decl_volatile)
+write_modifier_bytes_1 (type, decl_const, decl_volatile, count)
      register tree type;
      register int decl_const;
      register int decl_volatile;
+     register int count;
 {
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
+  /* Give up after searching 1000 levels, in case this is a recursive
+     pointer type.  Such types are possible in Ada, but it is not possible
+     to represent them in DWARF1 debug info.  */
+  if (count > 1000)
+    return;
+
   if (TYPE_READONLY (type) || decl_const)
     ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_const);
   if (TYPE_VOLATILE (type) || decl_volatile)
@@ -1344,12 +1510,12 @@ write_modifier_bytes (type, decl_const, decl_volatile)
     {
       case POINTER_TYPE:
        ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_pointer_to);
-       write_modifier_bytes (TREE_TYPE (type), 0, 0);
+       write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1);
        return;
 
       case REFERENCE_TYPE:
        ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_reference_to);
-       write_modifier_bytes (TREE_TYPE (type), 0, 0);
+       write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1);
        return;
 
       case ERROR_MARK:
@@ -1357,11 +1523,20 @@ write_modifier_bytes (type, decl_const, decl_volatile)
        return;
     }
 }
+
+static void
+write_modifier_bytes (type, decl_const, decl_volatile)
+     register tree type;
+     register int decl_const;
+     register int decl_volatile;
+{
+  write_modifier_bytes_1 (type, decl_const, decl_volatile, 0);
+}
 \f
 /* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the
    given input type is a Dwarf "fundamental" type.  Otherwise return zero.  */
 
-inline int
+static inline int
 type_is_fundamental (type)
      register tree type;
 {
@@ -1386,7 +1561,6 @@ type_is_fundamental (type)
       case METHOD_TYPE:
       case POINTER_TYPE:
       case REFERENCE_TYPE:
-      case STRING_TYPE:
       case FILE_TYPE:
       case OFFSET_TYPE:
       case LANG_TYPE:
@@ -1443,7 +1617,7 @@ equate_decl_number_to_die_number (decl)
    simply by re-generating the alternative name from the ..._TYPE node's
    UID number. */
 
-inline void
+static inline void
 equate_type_number_to_die_number (type)
      register tree type;
 {
@@ -1455,7 +1629,7 @@ equate_type_number_to_die_number (type)
      to get the equate to come out right, we need to get the main variant
      itself here.  */
 
-  type = TYPE_MAIN_VARIANT (type);
+  type = type_main_variant (type);
 
   sprintf (type_label, TYPE_NAME_FMT, TYPE_UID (type));
   sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum);
@@ -1476,7 +1650,7 @@ output_reg_number (rtl)
     }
   fprintf (asm_out_file, "\t%s\t0x%x",
           UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     {
       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
       PRINT_REG (rtl, 0, asm_out_file);
@@ -1563,6 +1737,15 @@ output_mem_loc_descriptor (rtl)
        ASM_OUTPUT_DWARF_DATA4 (asm_out_file, INTVAL (rtl));
        break;
 
+      case MULT:
+       /* If a pseudo-reg is optimized away, it is possible for it to
+          be replaced with a MEM containing a multiply.  Use a GNU extension
+          to describe it.  */
+       output_mem_loc_descriptor (XEXP (rtl, 0));
+       output_mem_loc_descriptor (XEXP (rtl, 1));
+       ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_MULT);
+       break;
+
       default:
        abort ();
     }
@@ -1617,79 +1800,73 @@ output_bound_representation (bound, dim_num, u_or_l)
   switch (TREE_CODE (bound))
     {
 
-      case ERROR_MARK:
-       return;
+    case ERROR_MARK:
+      return;
 
       /* All fixed-bounds are represented by INTEGER_CST nodes.         */
 
-      case INTEGER_CST:
-       ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                               (unsigned) TREE_INT_CST_LOW (bound));
-       break;
-
-      /* Dynamic bounds may be represented by NOP_EXPR nodes containing
-        SAVE_EXPR nodes.  */
-
-      case NOP_EXPR:
-       bound = TREE_OPERAND (bound, 0);
-       /* ... fall thru... */
-
-      case SAVE_EXPR:
-       {
-         char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
-         char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-         sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
-                               current_dienum, dim_num, u_or_l);
-
-         sprintf (end_label,   BOUND_END_LABEL_FMT,
-                               current_dienum, dim_num, u_or_l);
-
-         ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
-         ASM_OUTPUT_LABEL (asm_out_file, begin_label);
-
-         /* If we are working on a bound for a dynamic dimension in C,
-            the dynamic dimension in question had better have a static
-            (zero) lower bound and a dynamic *upper* bound.  */
+    case INTEGER_CST:
+      ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+                             (unsigned) TREE_INT_CST_LOW (bound));
+      break;
 
-         if (u_or_l != 'u')
-           abort ();
+    default:
 
-         /* If optimization is turned on, the SAVE_EXPRs that describe
-            how to access the upper bound values are essentially bogus.
-            They only describe (at best) how to get at these values at
-            the points in the generated code right after they have just
-            been computed.  Worse yet, in the typical case, the upper
-            bound values will not even *be* computed in the optimized
-            code, so these SAVE_EXPRs are entirely bogus.
-
-            In order to compensate for this fact, we check here to see
-            if optimization is enabled, and if so, we effectively create
-            an empty location description for the (unknown and unknowable)
-            upper bound.
-
-            This should not cause too much trouble for existing (stupid?)
-            debuggers because they have to deal with empty upper bounds
-            location descriptions anyway in order to be able to deal with
-            incomplete array types.
-
-            Of course an intelligent debugger (GDB?) should be able to
-            comprehend that a missing upper bound specification in a
-            array type used for a storage class `auto' local array variable
-            indicates that the upper bound is both unknown (at compile-
-            time) and unknowable (at run-time) due to optimization.
-         */
+      /* Dynamic bounds may be represented by NOP_EXPR nodes containing
+        SAVE_EXPR nodes, in which case we can do something, or as
+        an expression, which we cannot represent.  */
+      {
+       char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
+       char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+       sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
+                current_dienum, dim_num, u_or_l);
+
+       sprintf (end_label, BOUND_END_LABEL_FMT,
+                current_dienum, dim_num, u_or_l);
+
+       ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
+       ASM_OUTPUT_LABEL (asm_out_file, begin_label);
+
+       /* If optimization is turned on, the SAVE_EXPRs that describe
+          how to access the upper bound values are essentially bogus.
+          They only describe (at best) how to get at these values at
+          the points in the generated code right after they have just
+          been computed.  Worse yet, in the typical case, the upper
+          bound values will not even *be* computed in the optimized
+          code, so these SAVE_EXPRs are entirely bogus.
+
+          In order to compensate for this fact, we check here to see
+          if optimization is enabled, and if so, we effectively create
+          an empty location description for the (unknown and unknowable)
+          upper bound.
+
+          This should not cause too much trouble for existing (stupid?)
+          debuggers because they have to deal with empty upper bounds
+          location descriptions anyway in order to be able to deal with
+          incomplete array types.
+
+          Of course an intelligent debugger (GDB?) should be able to
+          comprehend that a missing upper bound specification in a
+          array type used for a storage class `auto' local array variable
+          indicates that the upper bound is both unknown (at compile-
+          time) and unknowable (at run-time) due to optimization. */
+
+       if (! optimize)
+         {
+           while (TREE_CODE (bound) == NOP_EXPR
+                  || TREE_CODE (bound) == CONVERT_EXPR)
+             bound = TREE_OPERAND (bound, 0);
 
-         if (! optimize)
-           output_loc_descriptor
-             (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
+           if (TREE_CODE (bound) == SAVE_EXPR)
+             output_loc_descriptor
+               (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX, 0));
+         }
 
-         ASM_OUTPUT_LABEL (asm_out_file, end_label);
-       }
-       break;
+       ASM_OUTPUT_LABEL (asm_out_file, end_label);
+      }
+      break;
 
-      default:
-       abort ();
     }
 }
 
@@ -1714,7 +1891,7 @@ output_enumeral_list (link)
 /* Given an unsigned value, round it up to the lowest multiple of `boundary'
    which is not less than the value itself.  */
 
-inline unsigned
+static inline unsigned
 ceiling (value, boundary)
      register unsigned value;
      register unsigned boundary;
@@ -1726,7 +1903,7 @@ ceiling (value, boundary)
    pointer to the declared type for the relevant field variable, or return
    `integer_type_node' if the given node turns out to be an ERROR_MARK node.  */
 
-inline tree
+static inline tree
 field_type (decl)
      register tree decl;
 {
@@ -1745,7 +1922,7 @@ field_type (decl)
    node, return the alignment in bits for the type, or else return
    BITS_PER_WORD if the node actually turns out to be an ERROR_MARK node.  */
 
-inline unsigned
+static inline unsigned
 simple_type_align_in_bits (type)
      register tree type;
 {
@@ -1758,7 +1935,7 @@ simple_type_align_in_bits (type)
    constant, or else return BITS_PER_WORD if the type actually turns out
    to be an ERROR_MARK node.  */
 
-inline unsigned
+static inline unsigned
 simple_type_size_in_bits (type)
      register tree type;
 {
@@ -1902,7 +2079,7 @@ field_byte_offset (decl)
 
 /* Generate an AT_sibling attribute.  */
 
-inline void
+static inline void
 sibling_attribute ()
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -1947,13 +2124,13 @@ location_attribute (rtl)
      suppress the generation of the entire location attribute because
      the absence of a location attribute in certain kinds of DIEs is
      used to indicate something else entirely... i.e. that the DIE
-     represents an object declaration, but not a definition.  So sayeth
+     represents an object declaration, but not a definition.  So saith
      the PLSIG.
   */
 
   if (! is_pseudo_reg (rtl)
       && (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0))))
-    output_loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX));
+    output_loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX, 0));
 
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
@@ -1977,17 +2154,21 @@ location_attribute (rtl)
    object" which will be given in the AT_byte_size attribute for this
    bit-field.  (See the `byte_size_attribute' function below.)  It is
    also used when calculating the value of the AT_bit_offset attribute.
-   (See the `bit_offset_attribute' function below.)
-*/
+   (See the `bit_offset_attribute' function below.)  */
 
 static void
-data_member_location_attribute (decl)
-     register tree decl;
+data_member_location_attribute (t)
+     register tree t;
 {
-  register unsigned object_offset_in_bytes = field_byte_offset (decl);
+  register unsigned object_offset_in_bytes;
   char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
   char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 
+  if (TREE_CODE (t) == TREE_VEC)
+    object_offset_in_bytes = TREE_INT_CST_LOW (BINFO_OFFSET (t));
+  else
+    object_offset_in_bytes = field_byte_offset (t);
+
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);
   sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);
   sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);
@@ -2100,68 +2281,107 @@ location_or_const_value_attribute (decl)
     return;
 
   if ((TREE_CODE (decl) != VAR_DECL) && (TREE_CODE (decl) != PARM_DECL))
-    abort ();
+    {
+      /* Should never happen.  */
+      abort ();
+      return;
+    }
 
-  /* Existing Dwarf debuggers need and expect the location descriptors for
-     formal parameters to reflect either the place where the parameters get
-     passed (if they are passed on the stack and in memory) or else the
-     (preserved) registers which the parameters get copied to during the
-     function prologue.
-
-     At least this is the way things are for most common CISC machines
-     (e.g. x86 and m68k) where parameters are passed in the stack, and for
-     most common RISC machines (e.g. i860 and m88k) where parameters are
-     passed in registers.
-
-     The rules for Sparc are a little weird for some reason.  The DWARF
-     generated by the USL C compiler for the Sparc/svr4 reference port says
-     that the parameters are passed in the stack.  I haven't figured out
-     how to duplicate that behavior here (for the Sparc) yet, or even if
-     I really need to.
-
-     Note that none of this is clearly spelled out in the current Dwarf
-     version 1 specification, but it's obvious if you look at the output of
-     the CI5 compiler, or if you try to use the svr4 SDB debugger.  Hopefully,
-     a later version of the Dwarf specification will clarify this.  For now,
-     we just need to generate the right thing.  Note that Dwarf version 2
-     will provide us with a means to describe *all* of the locations in which
-     a given variable or parameter resides (and the PC ranges over which it
-     occupies each one), but for now we can only describe one "location"
-     for each formal parameter passed, and so we just try to mimic existing
-     practice as much as possible.
+  /* Here we have to decide where we are going to say the parameter "lives"
+     (as far as the debugger is concerned).  We only have a couple of choices.
+     GCC provides us with DECL_RTL and with DECL_INCOMING_RTL.  DECL_RTL
+     normally indicates where the parameter lives during most of the activa-
+     tion of the function.  If optimization is enabled however, this could
+     be either NULL or else a pseudo-reg.  Both of those cases indicate that
+     the parameter doesn't really live anywhere (as far as the code generation
+     parts of GCC are concerned) during most of the function's activation.
+     That will happen (for example) if the parameter is never referenced
+     within the function.
+
+     We could just generate a location descriptor here for all non-NULL
+     non-pseudo values of DECL_RTL and ignore all of the rest, but we can
+     be a little nicer than that if we also consider DECL_INCOMING_RTL in
+     cases where DECL_RTL is NULL or is a pseudo-reg.
+
+     Note however that we can only get away with using DECL_INCOMING_RTL as
+     a backup substitute for DECL_RTL in certain limited cases.  In cases
+     where DECL_ARG_TYPE(decl) indicates the same type as TREE_TYPE(decl)
+     we can be sure that the parameter was passed using the same type as it
+     is declared to have within the function, and that its DECL_INCOMING_RTL
+     points us to a place where a value of that type is passed.  In cases
+     where DECL_ARG_TYPE(decl) and TREE_TYPE(decl) are different types
+     however, we cannot (in general) use DECL_INCOMING_RTL as a backup
+     substitute for DECL_RTL because in these cases, DECL_INCOMING_RTL
+     points us to a value of some type which is *different* from the type
+     of the parameter itself.  Thus, if we tried to use DECL_INCOMING_RTL
+     to generate a location attribute in such cases, the debugger would
+     end up (for example) trying to fetch a `float' from a place which
+     actually contains the first part of a `double'.  That would lead to
+     really incorrect and confusing output at debug-time, and we don't
+     want that now do we?
+
+     So in general, we DO NOT use DECL_INCOMING_RTL as a backup for DECL_RTL
+     in cases where DECL_ARG_TYPE(decl) != TREE_TYPE(decl).  There are a
+     couple of cute exceptions however.  On little-endian machines we can
+     get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE(decl) is
+     not the same as TREE_TYPE(decl) but only when DECL_ARG_TYPE(decl) is
+     an integral type which is smaller than TREE_TYPE(decl).  These cases
+     arise when (on a little-endian machine) a non-prototyped function has
+     a parameter declared to be of type `short' or `char'.  In such cases,
+     TREE_TYPE(decl) will be `short' or `char', DECL_ARG_TYPE(decl) will be
+     `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the
+     passed `int' value.  If the debugger then uses that address to fetch a
+     `short' or a `char' (on a little-endian machine) the result will be the
+     correct data, so we allow for such exceptional cases below.
+
+     Note that our goal here is to describe the place where the given formal
+     parameter lives during most of the function's activation (i.e. between
+     the end of the prologue and the start of the epilogue).  We'll do that
+     as best as we can.  Note however that if the given formal parameter is
+     modified sometime during the execution of the function, then a stack
+     backtrace (at debug-time) will show the function as having been called
+     with the *new* value rather than the value which was originally passed
+     in.  This happens rarely enough that it is not a major problem, but it
+     *is* a problem, and I'd like to fix it.  A future version of dwarfout.c
+     may generate two additional attributes for any given TAG_formal_parameter
+     DIE which will describe the "passed type" and the "passed location" for
+     the given formal parameter in addition to the attributes we now generate
+     to indicate the "declared type" and the "active location" for each
+     parameter.  This additional set of attributes could be used by debuggers
+     for stack backtraces.
+
+     Separately, note that sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL
+     can be NULL also.  This happens (for example) for inlined-instances of
+     inline function formal parameters which are never referenced.  This really
+     shouldn't be happening.  All PARM_DECL nodes should get valid non-NULL
+     DECL_INCOMING_RTL values, but integrate.c doesn't currently generate
+     these values for inlined instances of inline function parameters, so
+     when we see such cases, we are just SOL (shit-out-of-luck) for the time
+     being (until integrate.c gets fixed).
   */
 
-  if (TREE_CODE (decl) != PARM_DECL)
-    /*  If this decl is not a formal parameter, just use DECL_RTL.  */
-    rtl = DECL_RTL (decl);
-  else
-    {
-      if (GET_CODE (DECL_INCOMING_RTL (decl)) == MEM)
-        /* Parameter was passed in memory, so say that's where it lives.  */
-       rtl = DECL_INCOMING_RTL (decl);
-      else
-       {
-          /* Parameter was passed in a register, so say it lives in the
-            register it will be copied to during the prologue.  */
-          rtl = DECL_RTL (decl);
-
-         /* Note that in cases where the formal parameter is never used
-            and where this compilation is done with -O, the copying of
-            of an incoming register parameter to another register (in
-            the prologue) can be totally optimized away.  (In such cases
-            the DECL_RTL will indicate a pseudo-register.)  We could just
-            use the DECL_RTL (as we normally do for register parameters)
-            in these cases, but if we did that, we would end up generating
-            a null location descriptor.  (See `location_attribute' above.)
-            That would be acceptable (according to the DWARF spec) but it
-            is probably more useful to say that the formal resides where
-            it was passed instead of saying that it resides nowhere.  */
-         if (is_pseudo_reg (rtl))
-           rtl = DECL_INCOMING_RTL (decl);
-       }
-    }
+  /* Use DECL_RTL as the "location" unless we find something better.  */
+  rtl = DECL_RTL (decl);
 
-  if (rtl == NULL)
+  if (TREE_CODE (decl) == PARM_DECL)
+    if (rtl == NULL_RTX || is_pseudo_reg (rtl))
+      {
+       /* This decl represents a formal parameter which was optimized out.  */
+        register tree declared_type = type_main_variant (TREE_TYPE (decl));
+        register tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
+
+       /* Note that DECL_INCOMING_RTL may be NULL in here, but we handle
+          *all* cases where (rtl == NULL_RTX) just below.  */
+
+       if (declared_type == passed_type)
+         rtl = DECL_INCOMING_RTL (decl);
+       else if (! BYTES_BIG_ENDIAN)
+         if (TREE_CODE (declared_type) == INTEGER_TYPE)
+           if (TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
+             rtl = DECL_INCOMING_RTL (decl);
+      }
+
+  if (rtl == NULL_RTX)
     return;
 
   switch (GET_CODE (rtl))
@@ -2182,6 +2402,15 @@ location_or_const_value_attribute (decl)
       location_attribute (rtl);
       break;
 
+    case CONCAT:
+      /* ??? CONCAT is used for complex variables, which may have the real
+        part stored in one place and the imag part stored somewhere else.
+        DWARF1 has no way to describe a variable that lives in two different
+        places, so we just describe where the first part lives, and hope that
+        the second part is stored after it.  */
+      location_attribute (XEXP (rtl, 0));
+      break;
+
     default:
       abort ();                /* Should never happen.  */
     }
@@ -2190,7 +2419,7 @@ location_or_const_value_attribute (decl)
 /* Generate an AT_name attribute given some string value to be included as
    the value of the attribute. */
 
-inline void
+static inline void
 name_attribute (name_string)
      register char *name_string;
 {
@@ -2201,7 +2430,7 @@ name_attribute (name_string)
     }
 }
 
-inline void
+static inline void
 fund_type_attribute (ft_code)
      register unsigned ft_code;
 {
@@ -2229,7 +2458,7 @@ mod_fund_type_attribute (type, decl_const, decl_volatile)
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
 
-inline void
+static inline void
 user_def_type_attribute (type)
      register tree type;
 {
@@ -2262,7 +2491,7 @@ mod_u_d_type_attribute (type, decl_const, decl_volatile)
 }
 
 #ifdef USE_ORDERING_ATTRIBUTE
-inline void
+static inline void
 ordering_attribute (ordering)
      register unsigned ordering;
 {
@@ -2319,7 +2548,7 @@ subscript_data_attribute (type)
          if (! type_is_fundamental (domain))
            abort ();
 
-         /* Output the representation format byte for this dimension. */
+         /* Output the representation format byte for this dimension.  */
 
          ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file,
                                  FMT_CODE (1,
@@ -2365,7 +2594,7 @@ subscript_data_attribute (type)
        }
     }
 
-  /* Output the prefix byte that says that the element type is comming up.  */
+  /* Output the prefix byte that says that the element type is coming up.  */
 
   ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file, FMT_ET);
 
@@ -2433,10 +2662,9 @@ byte_size_attribute (tree_node)
 
    Note that it is the size (in bytes) of the hypothetical "containing
    object" which will be given in the AT_byte_size attribute for this
-   bit-field.  (See `byte_size_attribute' above.)
-*/
+   bit-field.  (See `byte_size_attribute' above.) */
 
-inline void
+static inline void
 bit_offset_attribute (decl)
     register tree decl;
 {
@@ -2468,19 +2696,18 @@ bit_offset_attribute (decl)
   highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT;
   highest_order_field_bit_offset = bitpos_int;
 
-#if (BYTES_BIG_ENDIAN == 0)
-  highest_order_field_bit_offset
-    += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
+  if (! BYTES_BIG_ENDIAN)
+    {
+      highest_order_field_bit_offset
+       += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
 
-  highest_order_object_bit_offset += simple_type_size_in_bits (type);
-#endif /* (BYTES_BIG_ENDIAN == 0) */
+      highest_order_object_bit_offset += simple_type_size_in_bits (type);
+    }
 
   bit_offset =
-#if (BYTES_BIG_ENDIAN == 0)
-         highest_order_object_bit_offset - highest_order_field_bit_offset;
-#else /* (BYTES_BIG_ENDIAN != 0) */
-         highest_order_field_bit_offset - highest_order_object_bit_offset;
-#endif /* (BYTES_BIG_ENDIAN != 0) */
+    (! BYTES_BIG_ENDIAN
+     ? highest_order_object_bit_offset - highest_order_field_bit_offset
+     : highest_order_field_bit_offset - highest_order_object_bit_offset);
 
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_offset);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, bit_offset);
@@ -2489,7 +2716,7 @@ bit_offset_attribute (decl)
 /* For a FIELD_DECL node which represents a bit field, output an attribute
    which specifies the length in bits of the given field.  */
 
-inline void
+static inline void
 bit_size_attribute (decl)
     register tree decl;
 {
@@ -2506,7 +2733,7 @@ bit_size_attribute (decl)
    all of the enumeration constants associated with the given enumeration
    type.  */
 
-inline void
+static inline void
 element_list_attribute (element)
      register tree element;
 {
@@ -2532,7 +2759,7 @@ element_list_attribute (element)
 /* Generate an AT_stmt_list attribute. These are normally present only in
    DIEs with a TAG_compile_unit tag.  */
 
-inline void
+static inline void
 stmt_list_attribute (label)
     register char *label;
 {
@@ -2544,7 +2771,7 @@ stmt_list_attribute (label)
 /* Generate an AT_low_pc attribute for a label DIE, a lexical_block DIE or
    for a subroutine DIE.  */
 
-inline void
+static inline void
 low_pc_attribute (asm_low_label)
      register char *asm_low_label;
 {
@@ -2555,7 +2782,7 @@ low_pc_attribute (asm_low_label)
 /* Generate an AT_high_pc attribute for a lexical_block DIE or for a
    subroutine DIE.  */
 
-inline void
+static inline void
 high_pc_attribute (asm_high_label)
     register char *asm_high_label;
 {
@@ -2565,7 +2792,7 @@ high_pc_attribute (asm_high_label)
 
 /* Generate an AT_body_begin attribute for a subroutine DIE.  */
 
-inline void
+static inline void
 body_begin_attribute (asm_begin_label)
      register char *asm_begin_label;
 {
@@ -2575,7 +2802,7 @@ body_begin_attribute (asm_begin_label)
 
 /* Generate an AT_body_end attribute for a subroutine DIE.  */
 
-inline void
+static inline void
 body_end_attribute (asm_end_label)
      register char *asm_end_label;
 {
@@ -2586,7 +2813,7 @@ body_end_attribute (asm_end_label)
 /* Generate an AT_language attribute given a LANG value.  These attributes
    are used only within TAG_compile_unit DIEs.  */
 
-inline void
+static inline void
 language_attribute (language_code)
      register unsigned language_code;
 {
@@ -2594,7 +2821,7 @@ language_attribute (language_code)
   ASM_OUTPUT_DWARF_DATA4 (asm_out_file, language_code);
 }
 
-inline void
+static inline void
 member_attribute (context)
     register tree context;
 {
@@ -2610,7 +2837,7 @@ member_attribute (context)
     }
 }
 
-inline void
+static inline void
 string_length_attribute (upper_bound)
      register tree upper_bound;
 {
@@ -2626,7 +2853,7 @@ string_length_attribute (upper_bound)
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
 
-inline void
+static inline void
 comp_dir_attribute (dirname)
      register char *dirname;
 {
@@ -2634,7 +2861,7 @@ comp_dir_attribute (dirname)
   ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
 }
 
-inline void
+static inline void
 sf_names_attribute (sf_names_start_label)
      register char *sf_names_start_label;
 {
@@ -2643,7 +2870,7 @@ sf_names_attribute (sf_names_start_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, sf_names_start_label);
 }
 
-inline void
+static inline void
 src_info_attribute (src_info_start_label)
      register char *src_info_start_label;
 {
@@ -2652,7 +2879,7 @@ src_info_attribute (src_info_start_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, src_info_start_label);
 }
 
-inline void
+static inline void
 mac_info_attribute (mac_info_start_label)
      register char *mac_info_start_label;
 {
@@ -2661,7 +2888,7 @@ mac_info_attribute (mac_info_start_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, mac_info_start_label);
 }
 
-inline void
+static inline void
 prototyped_attribute (func_type)
      register tree func_type;
 {
@@ -2673,7 +2900,7 @@ prototyped_attribute (func_type)
     }
 }
 
-inline void
+static inline void
 producer_attribute (producer)
      register char *producer;
 {
@@ -2681,7 +2908,7 @@ producer_attribute (producer)
   ASM_OUTPUT_DWARF_STRING (asm_out_file, producer);
 }
 
-inline void
+static inline void
 inline_attribute (decl)
      register tree decl;
 {
@@ -2692,7 +2919,7 @@ inline_attribute (decl)
     }
 }
 
-inline void
+static inline void
 containing_type_attribute (containing_type)
      register tree containing_type;
 {
@@ -2703,7 +2930,7 @@ containing_type_attribute (containing_type)
   ASM_OUTPUT_DWARF_REF (asm_out_file, label);
 }
 
-inline void
+static inline void
 abstract_origin_attribute (origin)
      register tree origin;
 {
@@ -2728,7 +2955,7 @@ abstract_origin_attribute (origin)
 }
 
 #ifdef DWARF_DECL_COORDINATES
-inline void
+static inline void
 src_coords_attribute (src_fileno, src_lineno)
      register unsigned src_fileno;
      register unsigned src_lineno;
@@ -2739,7 +2966,7 @@ src_coords_attribute (src_fileno, src_lineno)
 }
 #endif /* defined(DWARF_DECL_COORDINATES) */
 
-inline void
+static inline void
 pure_or_virtual_attribute (func_decl)
      register tree func_decl;
 {
@@ -2807,16 +3034,22 @@ type_attribute (type, decl_const, decl_volatile)
   register enum tree_code code = TREE_CODE (type);
   register int root_type_modified;
 
-  if (TREE_CODE (type) == ERROR_MARK)
+  if (code == ERROR_MARK)
     return;
 
   /* Handle a special case.  For functions whose return type is void,
      we generate *no* type attribute.  (Note that no object may have
      type `void', so this only applies to function return types.  */
 
-  if (TREE_CODE (type) == VOID_TYPE)
+  if (code == VOID_TYPE)
     return;
 
+  /* If this is a subtype, find the underlying type.  Eventually,
+     this should write out the appropriate subtype info.  */
+  while ((code == INTEGER_TYPE || code == REAL_TYPE)
+        && TREE_TYPE (type) != 0)
+    type = TREE_TYPE (type), code = TREE_CODE (type);
+
   root_type_modified = (code == POINTER_TYPE || code == REFERENCE_TYPE
                        || decl_const || decl_volatile
                        || TYPE_READONLY (type) || TYPE_VOLATILE (type));
@@ -2830,7 +3063,7 @@ type_attribute (type, decl_const, decl_volatile)
     if (root_type_modified)
        mod_u_d_type_attribute (type, decl_const, decl_volatile);
     else
-       /* We have to get the TYPE_MAIN_VARIANT here (and pass that to the
+       /* We have to get the type_main_variant here (and pass that to the
           `user_def_type_attribute' routine) because the ..._TYPE node we
           have might simply be a *copy* of some original type node (where
           the copy was created to help us keep track of typedef names)
@@ -2839,7 +3072,7 @@ type_attribute (type, decl_const, decl_volatile)
           is labeling a given type DIE for future reference, it always and
           only creates labels for DIEs representing *main variants*, and it
           never even knows about non-main-variants.)  */
-       user_def_type_attribute (TYPE_MAIN_VARIANT (type));
+       user_def_type_attribute (type_main_variant (type));
 }
 
 /* Given a tree pointer to a struct, class, union, or enum type node, return
@@ -2859,25 +3092,14 @@ type_tag (type)
       /* Find the IDENTIFIER_NODE for the type name.  */
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
        t = TYPE_NAME (type);
-#if 0
-      /* The g++ front end makes the TYPE_NAME of *each* tagged type point
-        to a TYPE_DECL node, regardless of whether or not a `typedef' was
-        involved.  This is distinctly different from what the gcc front-end
-        does.  It always makes the TYPE_NAME for each tagged type be either
-        NULL (signifying an anonymous tagged type) or else a pointer to an
-        IDENTIFIER_NODE.  Obviously, we would like to generate correct Dwarf
-        for both C and C++, but given this inconsistency in the TREE
-        representation of tagged types for C and C++ in the GNU front-ends,
-        we cannot support both languages correctly unless we introduce some
-        front-end specific code here, and rms objects to that, so we can
-        only generate correct Dwarf for one of these two languages.  C is
-        more important, so for now we'll do the right thing for C and let
-        g++ go fish.  */
 
-      else
-       if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+      /* The g++ front end makes the TYPE_NAME of *each* tagged type point to 
+         a TYPE_DECL node, regardless of whether or not a `typedef' was
+         involved.  */
+      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+              && ! DECL_IGNORED_P (TYPE_NAME (type)))
          t = DECL_NAME (TYPE_NAME (type));
-#endif
+
       /* Now get the name as a string, or invent one.  */
       if (t != 0)
        name = IDENTIFIER_POINTER (t);
@@ -2886,7 +3108,7 @@ type_tag (type)
   return (name == 0 || *name == '\0') ? 0 : name;
 }
 
-inline void
+static inline void
 dienum_push ()
 {
   /* Start by checking if the pending_sibling_stack needs to be expanded.
@@ -2907,13 +3129,13 @@ dienum_push ()
 /* Pop the sibling stack so that the most recently pushed DIEnum becomes the
    NEXT_DIE_NUM.  */
 
-inline void
+static inline void
 dienum_pop ()
 {
   pending_siblings--;
 }
 
-inline tree
+static inline tree
 member_declared_type (member)
      register tree member;
 {
@@ -2922,6 +3144,28 @@ member_declared_type (member)
           : TREE_TYPE (member);
 }
 
+/* Get the function's label, as described by its RTL.
+   This may be different from the DECL_NAME name used
+   in the source file.  */
+
+static char *
+function_start_label (decl)
+    register tree decl;
+{
+  rtx x;
+  char *fnname;
+
+  x = DECL_RTL (decl);
+  if (GET_CODE (x) != MEM)
+    abort ();
+  x = XEXP (x, 0);
+  if (GET_CODE (x) != SYMBOL_REF)
+              abort ();
+  fnname = XSTR (x, 0);
+  return fnname;
+}
+
+
 /******************************* DIEs ************************************/
 
 /* Output routines for individual types of DIEs.  */
@@ -2970,6 +3214,7 @@ output_set_type_die (arg)
 
 #if 0
 /* Implement this when there is a GNU FORTRAN or GNU Ada front end.  */
+
 static void
 output_entry_point_die (arg)
      register void *arg;
@@ -2991,7 +3236,7 @@ output_entry_point_die (arg)
   if (DECL_ABSTRACT (decl))
     equate_decl_number_to_die_number (decl);
   else
-    low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+    low_pc_attribute (function_start_label (decl));
 }
 #endif
 
@@ -3146,17 +3391,21 @@ output_global_subroutine_die (arg)
     equate_decl_number_to_die_number (decl);
   else
     {
-      if (! DECL_EXTERNAL (decl))
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && decl == current_function_decl)
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-         low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+         low_pc_attribute (function_start_label (decl));
          sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
          high_pc_attribute (label);
-         sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
-         body_begin_attribute (label);
-         sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
-         body_end_attribute (label);
+         if (use_gnu_debug_info_extensions)
+           {
+             sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+             body_begin_attribute (label);
+             sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+             body_end_attribute (label);
+           }
        }
     }
 }
@@ -3186,7 +3435,8 @@ output_global_variable_die (arg)
     equate_decl_number_to_die_number (decl);
   else
     {
-      if (!DECL_EXTERNAL (decl))
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && current_function_decl == decl_function_context (decl))
        location_or_const_value_attribute (decl);
     }
 }
@@ -3312,7 +3562,7 @@ output_member_die (arg)
   member_attribute (DECL_CONTEXT (decl));
   type_attribute (member_declared_type (decl),
                  TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
-  if (DECL_BIT_FIELD_TYPE (decl))      /* If this is a bit field... */
+  if (DECL_BIT_FIELD_TYPE (decl))      /* If this is a bit field...  */
     {
       byte_size_attribute (decl);
       bit_size_attribute (decl);
@@ -3325,9 +3575,9 @@ output_member_die (arg)
 /* Don't generate either pointer_type DIEs or reference_type DIEs.  Use
    modified types instead.
 
-   We keep this code here just in case these types of DIEs may be needed
-   to represent certain things in other languages (e.g. Pascal) someday.
-*/
+   We keep this code here just in case these types of DIEs may be
+   needed to represent certain things in other languages (e.g. Pascal)
+   someday.  */
 
 static void
 output_pointer_type_die (arg)
@@ -3390,6 +3640,10 @@ output_compile_unit_die (arg)
 
   if (strcmp (language_string, "GNU C++") == 0)
     language_attribute (LANG_C_PLUS_PLUS);
+  else if (strcmp (language_string, "GNU Ada") == 0)
+    language_attribute (LANG_ADA83);
+  else if (strcmp (language_string, "GNU F77") == 0)
+    language_attribute (LANG_FORTRAN77);
   else if (flag_traditional)
     language_attribute (LANG_C);
   else
@@ -3406,7 +3660,7 @@ output_compile_unit_die (arg)
       comp_dir_attribute (wd);
   }
 
-  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+  if (debug_info_level >= DINFO_LEVEL_NORMAL && use_gnu_debug_info_extensions)
     {
       sf_names_attribute (SFNAMES_BEGIN_LABEL);
       src_info_attribute (SRCINFO_BEGIN_LABEL);
@@ -3431,6 +3685,33 @@ output_string_type_die (arg)
 }
 
 static void
+output_inheritance_die (arg)
+     register void *arg;
+{
+  register tree binfo = arg;
+
+  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inheritance);
+  sibling_attribute ();
+  type_attribute (BINFO_TYPE (binfo), 0, 0);
+  data_member_location_attribute (binfo);
+  if (TREE_VIA_VIRTUAL (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
+      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+    }
+  if (TREE_VIA_PUBLIC (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
+      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+    }
+  else if (TREE_VIA_PROTECTED (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
+      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+    }
+}  
+
+static void
 output_structure_type_die (arg)
      register void *arg;
 {
@@ -3491,14 +3772,16 @@ output_local_subroutine_die (arg)
       if (TREE_ASM_WRITTEN (decl))
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-         low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+         low_pc_attribute (function_start_label (decl));
          sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
          high_pc_attribute (label);
-         sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
-         body_begin_attribute (label);
-         sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
-         body_end_attribute (label);
+         if (use_gnu_debug_info_extensions)
+           {
+             sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+             body_begin_attribute (label);
+             sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+             body_end_attribute (label);
+           }
        }
     }
 }
@@ -3668,11 +3951,11 @@ end_sibling_chain ()
    parameters as specified in some function type specification (except
    for those which appear as part of a function *definition*).
 
-   Note that we must be careful here to output all of the parameter DIEs
-   *before* we output any DIEs needed to represent the types of the formal
-   parameters.  This keeps svr4 SDB happy because it (incorrectly) thinks
-   that the first non-parameter DIE it sees ends the formal parameter list.
-*/
+   Note that we must be careful here to output all of the parameter
+   DIEs *before* we output any DIEs needed to represent the types of
+   the formal parameters.  This keeps svr4 SDB happy because it
+   (incorrectly) thinks that the first non-parameter DIE it sees ends
+   the formal parameter list.  */
 
 static void
 output_formal_types (function_or_method_type)
@@ -3785,10 +4068,9 @@ pend_type (type)
    been output are instead placed onto the pending_types_list.  Later on,
    we force these (temporarily pended) types to be output simply by calling
    `output_pending_types_for_scope' with an actual argument equal to the
-   true scope of the types we temporarily pended.
-*/
+   true scope of the types we temporarily pended.  */
 
-inline int
+static inline int
 type_ok_for_scope (type, scope)
     register tree type;
     register tree scope;
@@ -3805,7 +4087,9 @@ type_ok_for_scope (type, scope)
      (for C and C++ anyway) will be array types and function types.  */
 
   return is_tagged_type (type)
-        ? (TYPE_CONTEXT (type) == scope)
+        ? (TYPE_CONTEXT (type) == scope
+           || (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
+               && TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
         : (scope == NULL_TREE || ! is_tagged_type (scope));
 }
 
@@ -3818,8 +4102,7 @@ type_ok_for_scope (type, scope)
    Note that we have to process the list in beginning-to-end order,
    because the call made here to output_type may cause yet more types
    to be added to the end of the list, and we may have to output some
-   of them too.
-*/
+   of them too.  */
 
 static void
 output_pending_types_for_scope (containing_scope)
@@ -3869,11 +4152,22 @@ output_type (type, containing_scope)
      of this type (i.e. without any const or volatile qualifiers) so get
      the main variant (i.e. the unqualified version) of this type now.  */
 
-  type = TYPE_MAIN_VARIANT (type);
+  type = type_main_variant (type);
 
   if (TREE_ASM_WRITTEN (type))
     return;
 
+  /* If this is a nested type whose containing class hasn't been
+     written out yet, writing it out will cover this one, too.  */
+
+  if (TYPE_CONTEXT (type)
+      && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+      && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+    {
+      output_type (TYPE_CONTEXT (type), containing_scope);
+      return;
+    }
+
   /* Don't generate any DIEs for this type now unless it is OK to do so
      (based upon what `type_ok_for_scope' tells us).  */
 
@@ -3890,6 +4184,9 @@ output_type (type, containing_scope)
 
       case POINTER_TYPE:
       case REFERENCE_TYPE:
+       /* Prevent infinite recursion in cases where this is a recursive
+          type.  Recursive types are possible in Ada.  */
+       TREE_ASM_WRITTEN (type) = 1;
        /* For these types, all that is required is that we output a DIE
           (or a set of DIEs) to represent the "basis" type.  */
        output_type (TREE_TYPE (type), containing_scope);
@@ -3907,7 +4204,7 @@ output_type (type, containing_scope)
        break;
 
       case SET_TYPE:
-       output_type (TREE_TYPE (type), containing_scope);
+       output_type (TYPE_DOMAIN (type), containing_scope);
        output_die (output_set_type_die, type);
        break;
 
@@ -3916,11 +4213,6 @@ output_type (type, containing_scope)
        abort ();       /* No way to represent these in Dwarf yet!  */
        break;
 
-      case STRING_TYPE:
-       output_type (TREE_TYPE (type), containing_scope);
-       output_die (output_string_type_die, type);
-       break;
-
       case FUNCTION_TYPE:
        /* Force out return type (in case it wasn't forced out already).  */
        output_type (TREE_TYPE (type), containing_scope);
@@ -3937,17 +4229,23 @@ output_type (type, containing_scope)
        end_sibling_chain ();
        break;
 
-      case ARRAY_TYPE:
-       {
-         register tree element_type;
+      case ARRAY_TYPE: 
+       if (TYPE_STRING_FLAG (type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE)
+         {
+           output_type (TREE_TYPE (type), containing_scope);
+           output_die (output_string_type_die, type);
+         }
+       else
+         {
+           register tree element_type;
 
-         element_type = TREE_TYPE (type);
-         while (TREE_CODE (element_type) == ARRAY_TYPE)
-           element_type = TREE_TYPE (element_type);
+           element_type = TREE_TYPE (type);
+           while (TREE_CODE (element_type) == ARRAY_TYPE)
+             element_type = TREE_TYPE (element_type);
 
-         output_type (element_type, containing_scope);
-         output_die (output_array_type_die, type);
-       }
+           output_type (element_type, containing_scope);
+           output_die (output_array_type_die, type);
+         }
        break;
 
       case ENUMERAL_TYPE:
@@ -3983,10 +4281,12 @@ output_type (type, containing_scope)
           time, we will certainly know as much about each file-scope tagged
           type as we are ever going to know, so at that point in time, we
           can safely generate correct Dwarf descriptions for these file-
-          scope tagged types.
-       */
+          scope tagged types.  */
 
-       if (TYPE_SIZE (type) == 0 && TYPE_CONTEXT (type) == NULL && !finalizing)
+       if (TYPE_SIZE (type) == 0
+           && (TYPE_CONTEXT (type) == NULL
+               || TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
+           && !finalizing)
          return;       /* EARLY EXIT!  Avoid setting TREE_ASM_WRITTEN.  */
 
        /* Prevent infinite recursion in cases where the type of some
@@ -4034,10 +4334,23 @@ output_type (type, containing_scope)
 
        if (TYPE_SIZE (type))
          {
+           /* First output info about the base classes.  */
+           if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
+             {
+               register tree bases = TYPE_BINFO_BASETYPES (type);
+               register int n_bases = TREE_VEC_LENGTH (bases);
+               register int i;
+
+               for (i = 0; i < n_bases; i++)
+                 output_die (output_inheritance_die, TREE_VEC_ELT (bases, i));
+             }
+
+           ++in_class;
+
            {
              register tree normal_member;
 
-             /* First output info about the data members and type members.  */
+             /* Now output info about the data members and type members.  */
 
              for (normal_member = TYPE_FIELDS (type);
                   normal_member;
@@ -4046,32 +4359,18 @@ output_type (type, containing_scope)
            }
 
            {
-             register tree vec_base;
+             register tree func_member;
 
              /* Now output info about the function members (if any).  */
 
-             vec_base = TYPE_METHODS (type);
-             if (vec_base)
-               {
-                 register tree first_func_member = TREE_VEC_ELT (vec_base, 0);
-                 register tree func_member;
-
-                 /* This isn't documented, but the first element of the
-                    vector of member functions can be NULL in cases where
-                    the class type in question didn't have either a
-                    constructor or a destructor declared for it.  We have
-                    to make allowances for that here.  */
-
-                 if (first_func_member == NULL)
-                   first_func_member = TREE_VEC_ELT (vec_base, 1);
-
-                 for (func_member = first_func_member;
-                      func_member;
-                      func_member = TREE_CHAIN (func_member))
-                   output_decl (func_member, type);
-               }
+             for (func_member = TYPE_METHODS (type);
+                  func_member;
+                  func_member = TREE_CHAIN (func_member))
+               output_decl (func_member, type);
            }
 
+           --in_class;
+
            /* RECORD_TYPEs, UNION_TYPEs, and QUAL_UNION_TYPEs are themselves
               scopes (at least in C++) so we must now output any nested
               pending types which are local just to this type.  */
@@ -4113,7 +4412,7 @@ output_tagged_type_instantiation (type)
      sure that we have the main variant (i.e. the unqualified version) of
      this type now.  */
 
-  assert (type == TYPE_MAIN_VARIANT (type));
+  assert (type == type_main_variant (type));
 
   assert (TREE_ASM_WRITTEN (type));
 
@@ -4144,8 +4443,9 @@ output_tagged_type_instantiation (type)
    the things which are local to the given block.  */
 
 static void
-output_block (stmt)
+output_block (stmt, depth)
     register tree stmt;
+    int depth;
 {
   register int must_output_die = 0;
   register tree origin;
@@ -4183,7 +4483,7 @@ output_block (stmt)
         not represent a "body block inlining" before trying to set the
         `must_output_die' flag.  */
 
-      if (origin == NULL || ! is_body_block (origin))
+      if (! is_body_block (origin ? origin : stmt))
        {
          /* Determine if this block directly contains any "significant"
             local declarations which we will need to output DIEs for.  */
@@ -4217,32 +4517,35 @@ output_block (stmt)
      a "significant" local declaration gets restricted to include only
      inlined function instances and local (nested) function definitions.  */
 
-  if (must_output_die)
+  if (origin_code == FUNCTION_DECL && BLOCK_ABSTRACT (stmt))
+    /* We don't care about an abstract inlined subroutine.  */;
+  else if (must_output_die)
     {
       output_die ((origin_code == FUNCTION_DECL)
                    ? output_inlined_subroutine_die
                    : output_lexical_block_die,
                  stmt);
-      output_decls_for_scope (stmt);
+      output_decls_for_scope (stmt, depth);
       end_sibling_chain ();
     }
   else
-    output_decls_for_scope (stmt);
+    output_decls_for_scope (stmt, depth);
 }
 
 /* Output all of the decls declared within a given scope (also called
    a `binding contour') and (recursively) all of it's sub-blocks.  */
 
 static void
-output_decls_for_scope (stmt)
+output_decls_for_scope (stmt, depth)
      register tree stmt;
+     int depth;
 {
   /* Ignore blocks never really used to make RTL.  */
 
   if (! stmt || ! TREE_USED (stmt))
     return;
 
-  if (! BLOCK_ABSTRACT (stmt))
+  if (! BLOCK_ABSTRACT (stmt) && depth > 0)
     next_block_number++;
 
   /* Output the DIEs to represent all of the data objects, functions,
@@ -4267,10 +4570,28 @@ output_decls_for_scope (stmt)
     for (subblocks = BLOCK_SUBBLOCKS (stmt);
          subblocks;
          subblocks = BLOCK_CHAIN (subblocks))
-      output_block (subblocks);
+      output_block (subblocks, depth + 1);
   }
 }
 
+/* Is this a typedef we can avoid emitting?  */
+
+inline int
+is_redundant_typedef (decl)
+     register tree decl;
+{
+  if (TYPE_DECL_IS_STUB (decl))
+    return 1;
+  if (DECL_ARTIFICIAL (decl)
+      && DECL_CONTEXT (decl)
+      && is_tagged_type (DECL_CONTEXT (decl))
+      && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
+      && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
+    /* Also ignore the artificial member typedef for the class name.  */
+    return 1;
+  return 0;
+}
+
 /* Output Dwarf .debug information for a decl described by DECL.  */
 
 static void
@@ -4287,6 +4608,17 @@ output_decl (decl, containing_scope)
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
 
+  /* If a structure is declared within an initialization, e.g. as the
+     operand of a sizeof, then it will not have a name.  We don't want
+     to output a DIE for it, as the tree nodes are in the temporary obstack */
+
+  if ((TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+       || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
+      && ((DECL_NAME (decl) == 0 && TYPE_NAME (TREE_TYPE (decl)) == 0)
+         || (TYPE_FIELDS (TREE_TYPE (decl)) 
+             && (TREE_CODE (TYPE_FIELDS (TREE_TYPE (decl))) == ERROR_MARK))))
+    return;
+  
   /* If this ..._DECL node is marked to be ignored, then ignore it.
      But don't ignore a function definition, since that would screw
      up our count of blocks, and that it turn will completely screw up the
@@ -4305,11 +4637,11 @@ output_decl (decl, containing_scope)
 
     case FUNCTION_DECL:
       /* If we are in terse mode, don't output any DIEs to represent
-        mere external function declarations.  Also, if we are conforming
+        mere function declarations.  Also, if we are conforming
         to the DWARF version 1 specification, don't output DIEs for
-        mere external function declarations.  */
+        mere function declarations.  */
 
-      if (DECL_EXTERNAL (decl))
+      if (DECL_INITIAL (decl) == NULL_TREE)
 #if (DWARF_VERSION > 1)
        if (debug_info_level <= DINFO_LEVEL_TERSE)
 #endif
@@ -4320,6 +4652,13 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (TREE_TYPE (decl)), containing_scope);
 
+      {
+       /* And its containing type.  */
+       register tree origin = decl_class_context (decl);
+       if (origin)
+         output_type (origin, containing_scope);
+      }
+
       /* If the following DIE will represent a function definition for a
         function with "extern" linkage, output a special "pubnames" DIE
         label just ahead of the actual DIE.  A reference to this label
@@ -4352,182 +4691,139 @@ output_decl (decl, containing_scope)
         ends with a void_type_node then there should *not* be an ellipsis
         at the end.  */
 
-      /* In the case where we are describing an external function, all
+      /* In the case where we are describing a mere function declaration, all
         we need to do here (and all we *can* do here) is to describe
         the *types* of its formal parameters.  */
 
-      if (DECL_EXTERNAL (decl))
+      if (decl != current_function_decl || in_class)
        output_formal_types (TREE_TYPE (decl));
       else
        {
-         register tree arg_decls = DECL_ARGUMENTS (decl);
+         /* Generate DIEs to represent all known formal parameters */
 
-         {
-           register tree last_arg;
+         register tree arg_decls = DECL_ARGUMENTS (decl);
+         register tree parm;
+
+         /* WARNING!  Kludge zone ahead!  Here we have a special
+            hack for svr4 SDB compatibility.  Instead of passing the
+            current FUNCTION_DECL node as the second parameter (i.e.
+            the `containing_scope' parameter) to `output_decl' (as
+            we ought to) we instead pass a pointer to our own private
+            fake_containing_scope node.  That node is a RECORD_TYPE
+            node which NO OTHER TYPE may ever actually be a member of.
+
+            This pointer will ultimately get passed into `output_type'
+            as its `containing_scope' parameter.  `Output_type' will
+            then perform its part in the hack... i.e. it will pend
+            the type of the formal parameter onto the pending_types
+            list.  Later on, when we are done generating the whole
+            sequence of formal parameter DIEs for this function
+            definition, we will un-pend all previously pended types
+            of formal parameters for this function definition.
+
+            This whole kludge prevents any type DIEs from being
+            mixed in with the formal parameter DIEs.  That's good
+            because svr4 SDB believes that the list of formal
+            parameter DIEs for a function ends wherever the first
+            non-formal-parameter DIE appears.  Thus, we have to
+            keep the formal parameter DIEs segregated.  They must
+            all appear (consecutively) at the start of the list of
+            children for the DIE representing the function definition.
+            Then (and only then) may we output any additional DIEs
+            needed to represent the types of these formal parameters.
+         */
 
-           last_arg = (arg_decls && TREE_CODE (arg_decls) != ERROR_MARK)
-                       ? tree_last (arg_decls)
-                       : NULL;
+         /*
+            When generating DIEs, generate the unspecified_parameters
+            DIE instead if we come across the arg "__builtin_va_alist"
+         */
 
-           /* Generate DIEs to represent all known formal parameters, but
-              don't do it if this looks like a varargs function.  A given
-              function is considered to be a varargs function if (and only
-              if) its last named argument is named `__builtin_va_alist'.  */
+         for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
+           if (TREE_CODE (parm) == PARM_DECL)
+              {
+               if (DECL_NAME(parm) &&
+                   !strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)),
+                           "__builtin_va_alist") )
+                 output_die (output_unspecified_parameters_die, decl);
+               else
+                 output_decl (parm, fake_containing_scope);
+             }
 
-           if (! last_arg
-               || ! DECL_NAME (last_arg)
-               || strcmp (IDENTIFIER_POINTER (DECL_NAME (last_arg)),
-                          "__builtin_va_alist"))
-             {
-               register tree parm;
-
-               /* WARNING!  Kludge zone ahead!  Here we have a special
-                  hack for svr4 SDB compatibility.  Instead of passing the
-                  current FUNCTION_DECL node as the second parameter (i.e.
-                  the `containing_scope' parameter) to `output_decl' (as
-                  we ought to) we instead pass a pointer to our own private
-                  fake_containing_scope node.  That node is a RECORD_TYPE
-                  node which NO OTHER TYPE may ever actually be a member of.
-
-                  This pointer will ultimately get passed into `output_type'
-                  as its `containing_scope' parameter.  `Output_type' will
-                  then perform its part in the hack... i.e. it will pend
-                  the type of the formal parameter onto the pending_types
-                  list.  Later on, when we are done generating the whole
-                  sequence of formal parameter DIEs for this function
-                  definition, we will un-pend all previously pended types
-                  of formal parameters for this function definition.
-
-                  This whole kludge prevents any type DIEs from being
-                  mixed in with the formal parameter DIEs.  That's good
-                  because svr4 SDB believes that the list of formal
-                  parameter DIEs for a function ends wherever the first
-                  non-formal-parameter DIE appears.  Thus, we have to
-                  keep the formal parameter DIEs segregated.  They must
-                  all appear (consecutively) at the start of the list of
-                  children for the DIE representing the function definition.
-                  Then (and only then) may we output any additional DIEs
-                  needed to represent the types of these formal parameters.
-               */
-
-               for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
-                 if (TREE_CODE (parm) == PARM_DECL)
-                   output_decl (parm, fake_containing_scope);
-
-               /* Now that we have finished generating all of the DIEs to
-                  represent the formal parameters themselves, force out
-                  any DIEs needed to represent their types.  We do this
-                  simply by un-pending all previously pended types which
-                  can legitimately go into the chain of children DIEs for
-                  the current FUNCTION_DECL.  */
+         /*
+            Now that we have finished generating all of the DIEs to
+            represent the formal parameters themselves, force out
+            any DIEs needed to represent their types.  We do this
+            simply by un-pending all previously pended types which
+            can legitimately go into the chain of children DIEs for
+            the current FUNCTION_DECL.
+         */
 
-               output_pending_types_for_scope (decl);
-             }
-         }
+         output_pending_types_for_scope (decl);
 
-         /* Now try to decide if we should put an ellipsis at the end. */
+         /*
+           Decide whether we need a unspecified_parameters DIE at the end.
+           There are 2 more cases to do this for:
+           1) the ansi ... declaration - this is detectable when the end
+               of the arg list is not a void_type_node
+           2) an unprototyped function declaration (not a definition).  This
+               just means that we have no info about the parameters at all.
+         */
 
          {
-           register int has_ellipsis = TRUE;   /* default assumption */
            register tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
 
            if (fn_arg_types)
              {
-               /* This function declaration/definition was prototyped.  */
-
-               /* If the list of formal argument types ends with a
-                  void_type_node, then the formals list did *not* end
-                  with an ellipsis.  */
-
-               if (TREE_VALUE (tree_last (fn_arg_types)) == void_type_node)
-                 has_ellipsis = FALSE;
-             }
-           else
-             {
-               /* This function declaration/definition was not prototyped.  */
-
-               /* Note that all non-prototyped function *declarations* are
-                  assumed to represent varargs functions (until proven
-                  otherwise).  */
-
-               if (DECL_INITIAL (decl)) /* if this is a func definition */
-                 {
-                   if (!arg_decls)
-                     has_ellipsis = FALSE; /* no args == (void) */
-                   else
-                     {
-                       /* For a non-prototyped function definition which
-                          declares one or more formal parameters, if the name
-                          of the first formal parameter is *not*
-                          __builtin_va_alist then we must assume that this
-                          is *not* a varargs function.  */
-
-                       if (DECL_NAME (arg_decls)
-                         && strcmp (IDENTIFIER_POINTER (DECL_NAME (arg_decls)),
-                                    "__builtin_va_alist"))
-                         has_ellipsis = FALSE;
-                     }
-                 }
-             }
-
-           if (has_ellipsis)
-             output_die (output_unspecified_parameters_die, decl);
+             /* this is the prototyped case, check for ...  */
+             if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
+               output_die (output_unspecified_parameters_die, decl);
+              }
+            else
+              {
+             /* this is unprototyped, check for undefined (just declaration) */
+              if (!DECL_INITIAL (decl))
+                output_die (output_unspecified_parameters_die, decl);
+              }
          }
-       }
-
-      /* Output Dwarf info for all of the stuff within the body of the
-        function (if it has one - it may be just a declaration).  */
 
-      {
-       register tree outer_scope = DECL_INITIAL (decl);
+         /* Output Dwarf info for all of the stuff within the body of the
+            function (if it has one - it may be just a declaration).  */
 
-       if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
          {
-           /* Note that here, `outer_scope' is a pointer to the outermost
-              BLOCK node created to represent a function.
-              This outermost BLOCK actually represents the outermost
-              binding contour for the function, i.e. the contour in which
-              the function's formal parameters and labels get declared.
-
-              Curiously, it appears that the front end doesn't actually
-              put the PARM_DECL nodes for the current function onto the
-              BLOCK_VARS list for this outer scope.  (They are strung
-              off of the DECL_ARGUMENTS list for the function instead.)
-              The BLOCK_VARS list for the `outer_scope' does provide us
-              with a list of the LABEL_DECL nodes for the function however,
-              and we output DWARF info for those here.
-
-              Just within the `outer_scope' there will be another BLOCK
-              node representing the function's outermost pair of curly
-              braces.  We musn't generate a lexical_block DIE for this
-              outermost pair of curly braces because that is not really an
-              independent scope according to ANSI C rules.  Rather, it is
-              the same scope in which the parameters were declared.  */
-
-           {
-             register tree label;
-
-             for (label = BLOCK_VARS (outer_scope);
-                  label;
-                  label = TREE_CHAIN (label))
-               output_decl (label, outer_scope);
-           }
-
-           /* Note here that `BLOCK_SUBBLOCKS (outer_scope)' points to a
-              list of BLOCK nodes which is always only one element long.
-              That one element represents the outermost pair of curley
-              braces for the function body.  */
-
-           output_decls_for_scope (BLOCK_SUBBLOCKS (outer_scope));
+           register tree outer_scope = DECL_INITIAL (decl);
 
-           /* Finally, force out any pending types which are local to the
-              outermost block of this function definition.  These will
-              all have a TYPE_CONTEXT which points to the FUNCTION_DECL
-              node itself.  */
+           if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
+             {
+               /* Note that here, `outer_scope' is a pointer to the outermost
+                  BLOCK node created to represent a function.
+                  This outermost BLOCK actually represents the outermost
+                  binding contour for the function, i.e. the contour in which
+                  the function's formal parameters and labels get declared.
+
+                  Curiously, it appears that the front end doesn't actually
+                  put the PARM_DECL nodes for the current function onto the
+                  BLOCK_VARS list for this outer scope.  (They are strung
+                  off of the DECL_ARGUMENTS list for the function instead.)
+                  The BLOCK_VARS list for the `outer_scope' does provide us
+                  with a list of the LABEL_DECL nodes for the function however,
+                  and we output DWARF info for those here.
+
+                  Just within the `outer_scope' there will be a BLOCK node
+                  representing the function's outermost pair of curly braces,
+                  and any blocks used for the base and member initializers of
+                  a C++ constructor function.  */
+
+               output_decls_for_scope (outer_scope, 0);
+
+               /* Finally, force out any pending types which are local to the
+                  outermost block of this function definition.  These will
+                  all have a TYPE_CONTEXT which points to the FUNCTION_DECL
+                  node itself.  */
 
-           output_pending_types_for_scope (decl);
+               output_pending_types_for_scope (decl);
+             }
          }
-      }
+       }
 
       /* Generate a terminator for the list of stuff `owned' by this
         function.  */
@@ -4544,19 +4840,19 @@ output_decl (decl, containing_scope)
         a return type or a formal parameter type of some function.  */
 
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-       if (DECL_NAME (decl) != NULL
-           || ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
+       if (! TYPE_DECL_IS_STUB (decl)
+           || (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
           return;
 
-      /* In the special case of a null-named TYPE_DECL node (representing
-        the declaration of some type tag), if the given TYPE_DECL is
+      /* In the special case of a TYPE_DECL node representing
+        the declaration of some type tag, if the given TYPE_DECL is
         marked as having been instantiated from some other (original)
         TYPE_DECL node (e.g. one which was generated within the original
         definition of an inline function) we have to generate a special
         (abbreviated) TAG_structure_type, TAG_union_type, or
         TAG_enumeration-type DIE here.  */
 
-      if (! DECL_NAME (decl) && DECL_ABSTRACT_ORIGIN (decl))
+      if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
        {
          output_tagged_type_instantiation (TREE_TYPE (decl));
          return;
@@ -4564,16 +4860,7 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (decl), containing_scope);
 
-      /* Note that unlike the gcc front end (which generates a NULL named
-        TYPE_DECL node for each complete tagged type, each array type,
-        and each function type node created) the g++ front end generates
-        a *named* TYPE_DECL node for each tagged type node created.
-        Unfortunately, these g++ TYPE_DECL nodes cause us to output many
-        superfluous and unnecessary TAG_typedef DIEs here.  When g++ is
-        fixed to stop generating these superfluous named TYPE_DECL nodes,
-        the superfluous TAG_typedef DIEs will likewise cease.  */
-
-      if (DECL_NAME (decl))
+      if (! is_redundant_typedef (decl))
        /* Output a DIE to represent the typedef itself.  */
        output_die (output_typedef_die, decl);
       break;
@@ -4603,6 +4890,13 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (decl), containing_scope);
 
+      {
+       /* And its containing type.  */
+       register tree origin = decl_class_context (decl);
+       if (origin)
+         output_type (origin, containing_scope);
+      }
+
       /* If the following DIE will represent a data object definition for a
         data object with "extern" linkage, output a special "pubnames" DIE
         label just ahead of the actual DIE.  A reference to this label
@@ -4697,17 +4991,37 @@ dwarfout_file_scope_decl (decl, set_finalizing)
       if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl))
         return;
 
-      /* Ignore this FUNCTION_DECL if it refers to a file-scope extern
-        function declaration and if the declaration was never even
-        referenced from within this entire compilation unit.  We
-        suppress these DIEs in order to save space in the .debug section
-        (by eliminating entries which are probably useless).  Note that
-        we must not suppress block-local extern declarations (whether
-        used or not) because that would screw-up the debugger's name
-        lookup mechanism and cause it to miss things which really ought
-        to be in scope at a given point.  */
-
-      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
+      /* What we would really like to do here is to filter out all mere
+        file-scope declarations of file-scope functions which are never
+        referenced later within this translation unit (and keep all of
+        ones that *are* referenced later on) but we aren't clairvoyant,
+        so we have no idea which functions will be referenced in the
+        future (i.e. later on within the current translation unit).
+        So here we just ignore all file-scope function declarations
+        which are not also definitions.  If and when the debugger needs
+        to know something about these functions, it wil have to hunt
+        around and find the DWARF information associated with the
+        *definition* of the function.
+
+        Note that we can't just check `DECL_EXTERNAL' to find out which
+        FUNCTION_DECL nodes represent definitions and which ones represent
+        mere declarations.  We have to check `DECL_INITIAL' instead.  That's
+        because the C front-end supports some weird semantics for "extern
+        inline" function definitions.  These can get inlined within the
+        current translation unit (an thus, we need to generate DWARF info
+        for their abstract instances so that the DWARF info for the
+        concrete inlined instances can have something to refer to) but
+        the compiler never generates any out-of-lines instances of such
+        things (despite the fact that they *are* definitions).  The
+        important point is that the C front-end marks these "extern inline"
+        functions as DECL_EXTERNAL, but we need to generate DWARF for them
+        anyway.
+
+        Note that the C++ front-end also plays some similar games for inline
+        function definitions appearing within include files which also
+        contain `#pragma interface' pragmas.  */
+
+      if (DECL_INITIAL (decl) == NULL_TREE)
        return;
 
       if (TREE_PUBLIC (decl)
@@ -4858,7 +5172,7 @@ dwarfout_begin_block (blocknum)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  function_section (current_function_decl);
   sprintf (label, BLOCK_BEGIN_LABEL_FMT, blocknum);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 }
@@ -4872,7 +5186,7 @@ dwarfout_end_block (blocknum)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  function_section (current_function_decl);
   sprintf (label, BLOCK_END_LABEL_FMT, blocknum);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 }
@@ -4888,7 +5202,7 @@ dwarfout_label (insn)
     {
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-      text_section ();
+      function_section (current_function_decl);
       sprintf (label, INSN_LABEL_FMT, current_funcdef_number,
                                      (unsigned) INSN_UID (insn));
       ASM_OUTPUT_LABEL (asm_out_file, label);
@@ -4904,7 +5218,9 @@ dwarfout_begin_function ()
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  if (! use_gnu_debug_info_extensions)
+    return;
+  function_section (current_function_decl);
   sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 }
@@ -4917,7 +5233,9 @@ dwarfout_end_function ()
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  if (! use_gnu_debug_info_extensions)
+    return;
+  function_section (current_function_decl);
   sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 }
@@ -5009,8 +5327,7 @@ generate_new_sfname_entry ()
    calculated, and where at least one of the two symbol references is a
    forward reference.  (This bug could be tickled by our .debug_srcinfo
    entries if we don't output their corresponding .debug_sfnames entries
-   before them.)
-*/
+   before them.) */
 
 static unsigned
 lookup_filename (file_name)
@@ -5084,20 +5401,28 @@ dwarfout_line (filename, line)
      register char *filename;
      register unsigned line;
 {
-  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+  if (debug_info_level >= DINFO_LEVEL_NORMAL
+      /* We can't emit line number info for functions in separate sections,
+        because the assembler can't subtract labels in different sections.  */
+      && DECL_SECTION_NAME (current_function_decl) == NULL_TREE)
     {
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
       static unsigned last_line_entry_num = 0;
       static unsigned prev_file_entry_num = (unsigned) -1;
-      register unsigned this_file_entry_num = lookup_filename (filename);
+      register unsigned this_file_entry_num;
 
-      text_section ();
+      function_section (current_function_decl);
       sprintf (label, LINE_CODE_LABEL_FMT, ++last_line_entry_num);
       ASM_OUTPUT_LABEL (asm_out_file, label);
 
       fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
 
+      if (use_gnu_debug_info_extensions)
+       this_file_entry_num = lookup_filename (filename);
+      else
+       this_file_entry_num = (unsigned) -1;
+
+      ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
       if (this_file_entry_num != prev_file_entry_num)
         {
           char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -5133,6 +5458,9 @@ generate_macinfo_entry (type_and_offset, string)
      register char *type_and_offset;
      register char *string;
 {
+  if (! use_gnu_debug_info_extensions)
+    return;
+
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
   fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
@@ -5292,26 +5620,36 @@ dwarfout_init (asm_out_file, main_input_filename)
 
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     {
-      /* Output a starting label and an initial (compilation directory)
-        entry for the .debug_sfnames section.  The starting label will be
-        referenced by the initial entry in the .debug_srcinfo section.  */
+      if (use_gnu_debug_info_extensions)
+       {
+         /* Output a starting label and an initial (compilation directory)
+            entry for the .debug_sfnames section.  The starting label will be
+            referenced by the initial entry in the .debug_srcinfo section.  */
     
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
-      ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
-      {
-       register char *pwd = getpwd ();
-       register unsigned len = strlen (pwd);
-       register char *dirname = (char *) xmalloc (len + 2);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
+         ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
+         {
+           register char *pwd;
+           register unsigned len;
+           register char *dirname;
+
+           pwd = getpwd ();
+           if (!pwd)
+             pfatal_with_name ("getpwd");
+           len = strlen (pwd);
+           dirname = (char *) xmalloc (len + 2);
     
-       strcpy (dirname, pwd);
-       strcpy (dirname + len, "/");
-        ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
-        free (dirname);
-      }
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+           strcpy (dirname, pwd);
+           strcpy (dirname + len, "/");
+           ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+           free (dirname);
+         }
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
     
-      if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+      if (debug_info_level >= DINFO_LEVEL_VERBOSE
+         && use_gnu_debug_info_extensions)
        {
           /* Output a starting label for the .debug_macinfo section.  This
             label will be referenced by the AT_mac_info attribute in the
@@ -5332,21 +5670,24 @@ dwarfout_init (asm_out_file, main_input_filename)
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
       ASM_OUTPUT_POP_SECTION (asm_out_file);
     
-      /* Generate the initial entry for the .debug_srcinfo section.  */
-    
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
-      ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
+      if (use_gnu_debug_info_extensions)
+       {
+         /* Generate the initial entry for the .debug_srcinfo section.  */
+
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
+         ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
 #ifdef DWARF_TIMESTAMPS
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
+         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
 #else
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
+         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
 #endif
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
     
       /* Generate the initial entry for the .debug_pubnames section.  */
     
@@ -5418,7 +5759,7 @@ dwarfout_finish ()
      (or blame).  I didn't think of this scheme.  I just conformed to it.
   */
 
-  output_die (output_padded_null_die, (void *)0);
+  output_die (output_padded_null_die, (void *) 0);
   dienum_pop ();
 
   sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
@@ -5484,14 +5825,17 @@ dwarfout_finish ()
       ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
       ASM_OUTPUT_POP_SECTION (asm_out_file);
     
-      /* Output a terminating entry for the .debug_srcinfo section.  */
-    
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
-      ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
-                              LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+      if (use_gnu_debug_info_extensions)
+       {
+         /* Output a terminating entry for the .debug_srcinfo section.  */
+
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
+         ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
+                                  LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
 
       if (debug_info_level >= DINFO_LEVEL_VERBOSE)
        {