OSDN Git Service

[pf3gnuchains/gcc-fork.git] / gcc / dwarfout.c
index 4000b7a..4ab2747 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,45 +16,41 @@ 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"
 
 #ifdef DWARF_DEBUGGING_INFO
-#include <stdio.h>
+#include "system.h"
 #include "dwarf.h"
 #include "tree.h"
 #include "flags.h"
 #include "rtl.h"
+#include "hard-reg-set.h"
 #include "insn-config.h"
 #include "reload.h"
 #include "output.h"
 #include "defaults.h"
-
-#ifndef DWARF_VERSION
-#define DWARF_VERSION 1
-#endif
-
-/* #define NDEBUG 1 */
-#include <assert.h>
+#include "dwarfout.h"
+#include "toplev.h"
 
 #if defined(DWARF_TIMESTAMPS)
-#if defined(POSIX)
-#include <time.h>
-#else /* !defined(POSIX) */
-#include <sys/types.h>
-#if defined(__STDC__)
-extern time_t time (time_t *);
-#else /* !defined(__STDC__) */
-extern time_t time ();
-#endif /* !defined(__STDC__) */
+#if !defined(POSIX)
+extern time_t time PROTO ((time_t *)); /* FIXME: use NEED_DECLARATION_TIME */
 #endif /* !defined(POSIX) */
 #endif /* defined(DWARF_TIMESTAMPS) */
 
-extern char *getpwd ();
+/* We cannot use <assert.h> in GCC source, since that would include
+   GCC's assert.h, which may not be compatible with the host compiler.  */
+#undef assert
+#ifdef NDEBUG
+# define assert(e)
+#else
+# define assert(e) do { if (! (e)) abort (); } while (0)
+#endif
 
-extern char *index ();
-extern char *rindex ();
+extern char *getpwd PROTO((void));
 
 /* IMPORTANT NOTE: Please see the file README.DWARF for important details
    regarding the GNU implementation of Dwarf.  */
@@ -69,10 +63,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.  */
@@ -80,12 +72,11 @@ extern char *rindex ();
 #define ASM_COMMENT_START ";#"
 #endif
 
-/* Define a macro which, when given a pointer to some BLOCK node, returns
-   a pointer to the FUNCTION_DECL node from which the given BLOCK node
-   was instantiated (as an inline expansion).  This macro needs to be
-   defined properly in tree.h, however for the moment, we just fake it.  */
-
-#define BLOCK_INLINE_FUNCTION(block) 0
+/* How to print out a register name.  */
+#ifndef PRINT_REG
+#define PRINT_REG(RTX, CODE, FILE) \
+  fprintf ((FILE), "%s", reg_names[REGNO (RTX)])
+#endif
 
 /* Define a macro which returns non-zero for any tagged type which is
    used (directly or indirectly) in the specification of either some
@@ -104,6 +95,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 +172,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 +211,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;
 
@@ -217,7 +223,7 @@ static unsigned current_dienum;
    represents a function or data object defined in this compilation
    unit which has "extern" linkage.  */
 
-static next_pubname_number = 0;
+static int next_pubname_number = 0;
 
 #define NEXT_DIE_NUM pending_sibling_stack[pending_siblings-1]
 
@@ -284,13 +290,153 @@ static tree fake_containing_scope;
 
 static unsigned current_funcdef_number = 1;
 
+/* A pointer to the ..._DECL node which we have most recently been working
+   on.  We keep this around just in case something about it looks screwy
+   and we want to tell the user what the source coordinates for the actual
+   declaration are.  */
+
+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 tree decl_class_context                 PROTO((tree));
+#if 0
+static void output_unsigned_leb128     PROTO((unsigned long));
+static void output_signed_leb128       PROTO((long));
+#endif
+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));
+#ifdef USE_ORDERING_ATTRIBUTE
+static inline void ordering_attribute  PROTO((unsigned));
+#endif /* defined(USE_ORDERING_ATTRIBUTE) */
+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 language_attribute  PROTO((unsigned));
+static inline void member_attribute    PROTO((tree));
+#if 0
+static inline void string_length_attribute PROTO((tree));
+#endif
+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));
+#ifdef DWARF_DECL_COORDINATES
+static inline void src_coords_attribute PROTO((unsigned, unsigned));
+#endif /* defined(DWARF_DECL_COORDINATES) */
+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 *));
+#if 0
+static void output_entry_point_die     PROTO((void *));
+#endif
+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 *));
+#if 0
+static void output_pointer_type_die    PROTO((void *));
+static void output_reference_type_die  PROTO((void *));
+#endif
+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_inheritance_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 (*) PROTO((void *)), void *));
+static void end_sibling_chain          PROTO((void));
+static void output_formal_types                PROTO((tree));
+static void pend_type                  PROTO((tree));
+static int type_ok_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 generate_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 *));
+static int is_pseudo_reg               PROTO((rtx));
+static tree type_main_variant          PROTO((tree));
+static int is_tagged_type              PROTO((tree));
+static int is_redundant_typedef                PROTO((tree));
 \f
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
@@ -339,7 +485,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
@@ -401,157 +547,160 @@ static unsigned lookup_filename ();
 */
 
 #ifndef TEXT_BEGIN_LABEL
-#define TEXT_BEGIN_LABEL       ".L_text_b"
+#define TEXT_BEGIN_LABEL       "*.L_text_b"
 #endif
 #ifndef TEXT_END_LABEL
-#define TEXT_END_LABEL         ".L_text_e"
+#define TEXT_END_LABEL         "*.L_text_e"
 #endif
 
 #ifndef DATA_BEGIN_LABEL
-#define DATA_BEGIN_LABEL       ".L_data_b"
+#define DATA_BEGIN_LABEL       "*.L_data_b"
 #endif
 #ifndef DATA_END_LABEL
-#define DATA_END_LABEL         ".L_data_e"
+#define DATA_END_LABEL         "*.L_data_e"
 #endif
 
 #ifndef DATA1_BEGIN_LABEL
-#define DATA1_BEGIN_LABEL      ".L_data1_b"
+#define DATA1_BEGIN_LABEL      "*.L_data1_b"
 #endif
 #ifndef DATA1_END_LABEL
-#define DATA1_END_LABEL                ".L_data1_e"
+#define DATA1_END_LABEL                "*.L_data1_e"
 #endif
 
 #ifndef RODATA_BEGIN_LABEL
-#define RODATA_BEGIN_LABEL     ".L_rodata_b"
+#define RODATA_BEGIN_LABEL     "*.L_rodata_b"
 #endif
 #ifndef RODATA_END_LABEL
-#define RODATA_END_LABEL       ".L_rodata_e"
+#define RODATA_END_LABEL       "*.L_rodata_e"
 #endif
 
 #ifndef RODATA1_BEGIN_LABEL
-#define RODATA1_BEGIN_LABEL    ".L_rodata1_b"
+#define RODATA1_BEGIN_LABEL    "*.L_rodata1_b"
 #endif
 #ifndef RODATA1_END_LABEL
-#define RODATA1_END_LABEL      ".L_rodata1_e"
+#define RODATA1_END_LABEL      "*.L_rodata1_e"
 #endif
 
 #ifndef BSS_BEGIN_LABEL
-#define BSS_BEGIN_LABEL                ".L_bss_b"
+#define BSS_BEGIN_LABEL                "*.L_bss_b"
 #endif
 #ifndef BSS_END_LABEL
-#define BSS_END_LABEL          ".L_bss_e"
+#define BSS_END_LABEL          "*.L_bss_e"
 #endif
 
 #ifndef LINE_BEGIN_LABEL
-#define LINE_BEGIN_LABEL       ".L_line_b"
+#define LINE_BEGIN_LABEL       "*.L_line_b"
 #endif
 #ifndef LINE_LAST_ENTRY_LABEL
-#define LINE_LAST_ENTRY_LABEL  ".L_line_last"
+#define LINE_LAST_ENTRY_LABEL  "*.L_line_last"
 #endif
 #ifndef LINE_END_LABEL
-#define LINE_END_LABEL         ".L_line_e"
+#define LINE_END_LABEL         "*.L_line_e"
 #endif
 
 #ifndef DEBUG_BEGIN_LABEL
-#define DEBUG_BEGIN_LABEL      ".L_debug_b"
+#define DEBUG_BEGIN_LABEL      "*.L_debug_b"
 #endif
 #ifndef SFNAMES_BEGIN_LABEL
-#define SFNAMES_BEGIN_LABEL    ".L_sfnames_b"
+#define SFNAMES_BEGIN_LABEL    "*.L_sfnames_b"
 #endif
 #ifndef SRCINFO_BEGIN_LABEL
-#define SRCINFO_BEGIN_LABEL    ".L_srcinfo_b"
+#define SRCINFO_BEGIN_LABEL    "*.L_srcinfo_b"
 #endif
 #ifndef MACINFO_BEGIN_LABEL
-#define MACINFO_BEGIN_LABEL    ".L_macinfo_b"
+#define MACINFO_BEGIN_LABEL    "*.L_macinfo_b"
 #endif
 
 #ifndef DIE_BEGIN_LABEL_FMT
-#define DIE_BEGIN_LABEL_FMT    ".L_D%u"
+#define DIE_BEGIN_LABEL_FMT    "*.L_D%u"
 #endif
 #ifndef DIE_END_LABEL_FMT
-#define DIE_END_LABEL_FMT      ".L_D%u_e"
+#define DIE_END_LABEL_FMT      "*.L_D%u_e"
 #endif
 #ifndef PUB_DIE_LABEL_FMT
-#define PUB_DIE_LABEL_FMT      ".L_P%u"
+#define PUB_DIE_LABEL_FMT      "*.L_P%u"
 #endif
 #ifndef INSN_LABEL_FMT
-#define INSN_LABEL_FMT         ".L_I%u_%u"
+#define INSN_LABEL_FMT         "*.L_I%u_%u"
 #endif
 #ifndef BLOCK_BEGIN_LABEL_FMT
-#define BLOCK_BEGIN_LABEL_FMT  ".L_B%u"
+#define BLOCK_BEGIN_LABEL_FMT  "*.L_B%u"
 #endif
 #ifndef BLOCK_END_LABEL_FMT
-#define BLOCK_END_LABEL_FMT    ".L_B%u_e"
+#define BLOCK_END_LABEL_FMT    "*.L_B%u_e"
 #endif
 #ifndef SS_BEGIN_LABEL_FMT
-#define SS_BEGIN_LABEL_FMT     ".L_s%u"
+#define SS_BEGIN_LABEL_FMT     "*.L_s%u"
 #endif
 #ifndef SS_END_LABEL_FMT
-#define SS_END_LABEL_FMT       ".L_s%u_e"
+#define SS_END_LABEL_FMT       "*.L_s%u_e"
 #endif
 #ifndef EE_BEGIN_LABEL_FMT
-#define EE_BEGIN_LABEL_FMT     ".L_e%u"
+#define EE_BEGIN_LABEL_FMT     "*.L_e%u"
 #endif
 #ifndef EE_END_LABEL_FMT
-#define EE_END_LABEL_FMT       ".L_e%u_e"
+#define EE_END_LABEL_FMT       "*.L_e%u_e"
 #endif
 #ifndef MT_BEGIN_LABEL_FMT
-#define MT_BEGIN_LABEL_FMT     ".L_t%u"
+#define MT_BEGIN_LABEL_FMT     "*.L_t%u"
 #endif
 #ifndef MT_END_LABEL_FMT
-#define MT_END_LABEL_FMT       ".L_t%u_e"
+#define MT_END_LABEL_FMT       "*.L_t%u_e"
 #endif
 #ifndef LOC_BEGIN_LABEL_FMT
-#define LOC_BEGIN_LABEL_FMT    ".L_l%u"
+#define LOC_BEGIN_LABEL_FMT    "*.L_l%u"
 #endif
 #ifndef LOC_END_LABEL_FMT
-#define LOC_END_LABEL_FMT      ".L_l%u_e"
+#define LOC_END_LABEL_FMT      "*.L_l%u_e"
 #endif
 #ifndef BOUND_BEGIN_LABEL_FMT
-#define BOUND_BEGIN_LABEL_FMT  ".L_b%u_%u_%c"
+#define BOUND_BEGIN_LABEL_FMT  "*.L_b%u_%u_%c"
 #endif
 #ifndef BOUND_END_LABEL_FMT
-#define BOUND_END_LABEL_FMT    ".L_b%u_%u_%c_e"
+#define BOUND_END_LABEL_FMT    "*.L_b%u_%u_%c_e"
 #endif
 #ifndef DERIV_BEGIN_LABEL_FMT
-#define DERIV_BEGIN_LABEL_FMT  ".L_d%u"
+#define DERIV_BEGIN_LABEL_FMT  "*.L_d%u"
 #endif
 #ifndef DERIV_END_LABEL_FMT
-#define DERIV_END_LABEL_FMT    ".L_d%u_e"
+#define DERIV_END_LABEL_FMT    "*.L_d%u_e"
 #endif
 #ifndef SL_BEGIN_LABEL_FMT
-#define SL_BEGIN_LABEL_FMT     ".L_sl%u"
+#define SL_BEGIN_LABEL_FMT     "*.L_sl%u"
 #endif
 #ifndef SL_END_LABEL_FMT
-#define SL_END_LABEL_FMT       ".L_sl%u_e"
+#define SL_END_LABEL_FMT       "*.L_sl%u_e"
+#endif
+#ifndef BODY_BEGIN_LABEL_FMT
+#define BODY_BEGIN_LABEL_FMT   "*.L_b%u"
+#endif
+#ifndef BODY_END_LABEL_FMT
+#define BODY_END_LABEL_FMT     "*.L_b%u_e"
 #endif
 #ifndef FUNC_END_LABEL_FMT
-#define FUNC_END_LABEL_FMT     ".L_f%u_e"
+#define FUNC_END_LABEL_FMT     "*.L_f%u_e"
 #endif
 #ifndef TYPE_NAME_FMT
-#define TYPE_NAME_FMT          ".L_T%u"
+#define TYPE_NAME_FMT          "*.L_T%u"
 #endif
 #ifndef DECL_NAME_FMT
-#define DECL_NAME_FMT          ".L_E%u"
+#define DECL_NAME_FMT          "*.L_E%u"
 #endif
 #ifndef LINE_CODE_LABEL_FMT
-#define LINE_CODE_LABEL_FMT    ".L_LC%u"
+#define LINE_CODE_LABEL_FMT    "*.L_LC%u"
 #endif
 #ifndef SFNAMES_ENTRY_LABEL_FMT
-#define SFNAMES_ENTRY_LABEL_FMT        ".L_F%u"
+#define SFNAMES_ENTRY_LABEL_FMT        "*.L_F%u"
 #endif
 #ifndef LINE_ENTRY_LABEL_FMT
-#define LINE_ENTRY_LABEL_FMT   ".L_LE%u"
+#define LINE_ENTRY_LABEL_FMT   "*.L_LE%u"
 #endif
 \f
 /* Definitions of defaults for various types of primitive assembly language
    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) \
@@ -563,21 +712,6 @@ static unsigned lookup_filename ();
   fprintf ((FILE), "\t%s\n", POPSECTION_ASM_OP)
 #endif
 
-#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");                                           \
-  } while (0)
-#endif
-
 #ifndef ASM_OUTPUT_DWARF_DELTA2
 #define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)                    \
  do {  fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);             \
@@ -603,7 +737,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));                                              \
@@ -615,7 +749,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));                                              \
@@ -626,7 +760,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));                                              \
@@ -638,7 +772,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));                                              \
@@ -649,7 +783,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));                                              \
@@ -660,7 +794,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));                                              \
@@ -723,24 +857,24 @@ static unsigned lookup_filename ();
   } while (0)
 #endif
 
+/* ASM_OUTPUT_DWARF_STRING is defined to output an ascii string, but to
+   NOT issue a trailing newline. We define ASM_OUTPUT_DWARF_STRING_NEWLINE
+   based on whether ASM_OUTPUT_DWARF_STRING is defined or not. If it is
+   defined, we call it, then issue the line feed. If not, we supply a
+   default defintion of calling ASM_OUTPUT_ASCII */
+
 #ifndef ASM_OUTPUT_DWARF_STRING
-#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
+#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
   ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1)
+#else
+#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
+  ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n") 
 #endif
+
 \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
+inline static int
 is_pseudo_reg (rtl)
      register rtx rtl;
 {
@@ -749,6 +883,38 @@ is_pseudo_reg (rtl)
              && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
 }
 
+inline static 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 static int
+is_tagged_type (type)
+     register tree type;
+{
+  register enum tree_code code = TREE_CODE (type);
+
+  return (code == RECORD_TYPE || code == UNION_TYPE
+         || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
+}
+
 static char *
 dwarf_tag_name (tag)
      register unsigned tag;
@@ -870,6 +1036,8 @@ dwarf_attr_name (attr)
     case AT_src_info:                  return "AT_src_info";
     case AT_mac_info:                  return "AT_mac_info";
     case AT_src_coords:                        return "AT_src_coords";
+    case AT_body_begin:                        return "AT_body_begin";
+    case AT_body_end:                  return "AT_body_end";
 
     default:                           return "AT_<unknown>";
     }
@@ -924,6 +1092,7 @@ dwarf_fmt_byte_name (fmt)
     default:           return "FMT_<unknown>";
     }
 }
+
 static char *
 dwarf_fund_type_name (ft)
      register unsigned ft;
@@ -970,37 +1139,176 @@ 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";
     case FT_real96:            return "FT_real96";
     case FT_real128:           return "FT_real128";
 
-    default:                   return "<unknown fundamental type>";
+    default:                   return "FT_<unknown>";
+    }
+}
+
+/* Determine the "ultimate origin" of a decl.  The decl may be an
+   inlined instance of an inlined instance of a decl which is local
+   to an inline function, so we have to trace all of the way back
+   through the origin chain to find out what sort of node actually
+   served as the original seed for the given block.  */
+
+static tree
+decl_ultimate_origin (decl)
+     register tree decl;
+{
+#ifdef ENABLE_CHECKING 
+  if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
+    /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+       most distant ancestor, this should never happen.  */
+    abort ();
+#endif
+
+  return DECL_ABSTRACT_ORIGIN (decl);
+}
+
+/* Determine the "ultimate origin" of a block.  The block may be an
+   inlined instance of an inlined instance of a block which is local
+   to an inline function, so we have to trace all of the way back
+   through the origin chain to find out what sort of node actually
+   served as the original seed for the given block.  */
+
+static tree
+block_ultimate_origin (block)
+     register tree block;
+{
+  register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
+
+  if (immediate_origin == NULL)
+    return NULL;
+  else
+    {
+      register tree ret_val;
+      register tree lookahead = immediate_origin;
+
+      do
+       {
+         ret_val = lookahead;
+         lookahead = (TREE_CODE (ret_val) == BLOCK)
+                      ? BLOCK_ABSTRACT_ORIGIN (ret_val)
+                      : NULL;
+       }
+      while (lookahead != NULL && lookahead != ret_val);
+      return ret_val;
+    }
+}
+
+/* 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;
+}
+
+#if 0
+static void
+output_unsigned_leb128 (value)
+     register unsigned long value;
+{
+  register unsigned long orig_value = value;
+
+  do
+    {
+      register unsigned byte = (value & 0x7f);
+
+      value >>= 7;
+      if (value != 0)  /* more bytes to follow */
+       byte |= 0x80;
+      fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
+      if (flag_debug_asm && value == 0)
+       fprintf (asm_out_file, "\t%s ULEB128 number - value = %lu",
+                ASM_COMMENT_START, orig_value);
+      fputc ('\n', asm_out_file);
+    }
+  while (value != 0);
+}
+
+static void
+output_signed_leb128 (value)
+     register long value;
+{
+  register long orig_value = value;
+  register int negative = (value < 0);
+  register int more;
+
+  do
+    {
+      register unsigned byte = (value & 0x7f);
+
+      value >>= 7;
+      if (negative)
+       value |= 0xfe000000;  /* manually sign extend */
+      if (((value == 0) && ((byte & 0x40) == 0))
+          || ((value == -1) && ((byte & 0x40) == 1)))
+       more = 0;
+      else
+       {
+         byte |= 0x80;
+         more = 1;
+       }
+      fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
+      if (flag_debug_asm && more == 0)
+       fprintf (asm_out_file, "\t%s SLEB128 number - value = %ld",
+                ASM_COMMENT_START, orig_value);
+      fputc ('\n', asm_out_file);
     }
+  while (more);
 }
+#endif
 \f
 /**************** utility functions for attribute functions ******************/
 
 /* Given a pointer to a BLOCK node return non-zero if (and only if) the
-   node in question represents the outermost block (i.e. the "body block")
-   of a function or method.
-
-   For any BLOCK node representing a "body block", the BLOCK_SUPERCONTEXT
-   of the node will point to another BLOCK node which represents the outer-
-   most (function) scope for the function or method.  The BLOCK_SUPERCONTEXT
-   of that node in turn will point to the relevant FUNCTION_DECL node.
+   node in question represents the outermost pair of curly braces (i.e.
+   the "body block") of a function or method.
+
+   For any BLOCK node representing a "body block" of a function or method,
+   the BLOCK_SUPERCONTEXT of the node will point to another BLOCK node
+   which represents the outermost (function) scope for the function or
+   method (i.e. the one which includes the formal parameters).  The
+   BLOCK_SUPERCONTEXT of *that* node in turn will point to the relevant
+   FUNCTION_DECL node.
 */
 
-inline int
+static inline int
 is_body_block (stmt)
      register tree stmt;
 {
-  register enum tree_code code
-    = TREE_CODE (BLOCK_SUPERCONTEXT (BLOCK_SUPERCONTEXT (stmt)));
+  if (TREE_CODE (stmt) == BLOCK)
+    {
+      register tree parent = BLOCK_SUPERCONTEXT (stmt);
 
-  return (code == FUNCTION_DECL);
+      if (TREE_CODE (parent) == BLOCK)
+       {
+         register tree grandparent = BLOCK_SUPERCONTEXT (parent);
+
+         if (TREE_CODE (grandparent) == FUNCTION_DECL)
+           return 1;
+       }
+    }
+  return 0;
 }
 
 /* Given a pointer to a tree node for some type, return a Dwarf fundamental
@@ -1016,9 +1324,9 @@ is_body_block (stmt)
    information about the precise way in which the type was originally
    specified, as in:
 
-       typedef signed int field_type;
+       typedef signed int my_type;
 
-       struct s { field_type f; };
+       struct s { my_type f; };
 
    Since we may be stuck here without enought information to do exactly
    what is called for in the Dwarf draft specification, we do the best
@@ -1114,7 +1422,16 @@ fundamental_type_code (type)
          }
 
        if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE)
-         return FT_dbl_prec_float;
+         {
+           /* On the SH, when compiling with -m3e or -m4-single-only, both
+              float and double are 32 bits.  But since the debugger doesn't
+              know about the subtarget, it always thinks double is 64 bits.
+              So we have to tell the debugger that the type is float to
+              make the output of the 'print' command etc. readable.  */
+           if (DOUBLE_TYPE_SIZE == FLOAT_TYPE_SIZE && FLOAT_TYPE_SIZE == 32)
+             return FT_float;
+           return FT_dbl_prec_float;
+         }
        if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
          return FT_float;
 
@@ -1152,10 +1469,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))
@@ -1165,25 +1486,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)
@@ -1192,12 +1530,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:
@@ -1205,11 +1543,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;
 {
@@ -1228,12 +1575,12 @@ type_is_fundamental (type)
       case ARRAY_TYPE:
       case RECORD_TYPE:
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
       case ENUMERAL_TYPE:
       case FUNCTION_TYPE:
       case METHOD_TYPE:
       case POINTER_TYPE:
       case REFERENCE_TYPE:
-      case STRING_TYPE:
       case FILE_TYPE:
       case OFFSET_TYPE:
       case LANG_TYPE:
@@ -1290,7 +1637,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;
 {
@@ -1302,13 +1649,35 @@ 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);
   ASM_OUTPUT_DEF (asm_out_file, type_label, die_label);
 }
 
+static void
+output_reg_number (rtl)
+     register rtx rtl;
+{
+  register unsigned regno = REGNO (rtl);
+
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    {
+      warning_with_decl (dwarf_last_decl, "internal regno botch: regno = %d\n",
+                        regno);
+      regno = 0;
+    }
+  fprintf (asm_out_file, "\t%s\t0x%x",
+          UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));
+  if (flag_debug_asm)
+    {
+      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
+      PRINT_REG (rtl, 0, asm_out_file);
+    }
+  fputc ('\n', asm_out_file);
+}
+
 /* The following routine is a nice and simple transducer.  It converts the
    RTL for a variable or parameter (resident in memory) into an equivalent
    Dwarf representation of a mechanism for getting the address of that same
@@ -1345,15 +1714,25 @@ output_mem_loc_descriptor (rtl)
 
        /* Whenever a register number forms a part of the description of
           the method for calculating the (dynamic) address of a memory
-          resident object, Dwarf rules require the register number to
+          resident object, DWARF rules require the register number to
           be referred to as a "base register".  This distinction is not
           based in any way upon what category of register the hardware
           believes the given register belongs to.  This is strictly
-          Dwarf terminology we're dealing with here.  */
+          DWARF terminology we're dealing with here.
+
+          Note that in cases where the location of a memory-resident data
+          object could be expressed as:
+
+                   OP_ADD (OP_BASEREG (basereg), OP_CONST (0))
+
+          the actual DWARF location descriptor that we generate may just
+          be OP_BASEREG (basereg).  This may look deceptively like the
+          object in question was allocated to a register (rather than
+          in memory) so DWARF consumers need to be aware of the subtle
+          distinction between OP_REG and OP_BASEREG.  */
 
        ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_BASEREG);
-        ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                               DBX_REGISTER_NUMBER (REGNO (rtl)));
+       output_reg_number (rtl);
        break;
 
       case MEM:
@@ -1378,6 +1757,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 ();
     }
@@ -1408,8 +1796,7 @@ output_loc_descriptor (rtl)
 
     case REG:
        ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_REG);
-        ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                               DBX_REGISTER_NUMBER (REGNO (rtl)));
+       output_reg_number (rtl);
        break;
 
     case MEM:
@@ -1433,79 +1820,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, 0));
+           if (TREE_CODE (bound) == SAVE_EXPR)
+             output_loc_descriptor
+               (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
+         }
 
-         ASM_OUTPUT_LABEL (asm_out_file, end_label);
-       }
-       break;
+       ASM_OUTPUT_LABEL (asm_out_file, end_label);
+      }
+      break;
 
-      default:
-       abort ();
     }
 }
 
@@ -1522,221 +1903,318 @@ output_enumeral_list (link)
       output_enumeral_list (TREE_CHAIN (link));
       ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
                              (unsigned) TREE_INT_CST_LOW (TREE_VALUE (link)));
-      ASM_OUTPUT_DWARF_STRING (asm_out_file,
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
                               IDENTIFIER_POINTER (TREE_PURPOSE (link)));
     }
 }
 
-/****************************** attributes *********************************/
-
-/* The following routines are responsible for writing out the various types
-   of Dwarf attributes (and any following data bytes associated with them).
-   These routines are listed in order based on the numerical codes of their
-   associated attributes.  */
-
-/* Generate an AT_sibling attribute.  */
+/* Given an unsigned value, round it up to the lowest multiple of `boundary'
+   which is not less than the value itself.  */
 
-inline void
-sibling_attribute ()
+static inline unsigned
+ceiling (value, boundary)
+     register unsigned value;
+     register unsigned boundary;
 {
-  char label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_sibling);
-  sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
-  ASM_OUTPUT_DWARF_REF (asm_out_file, label);
+  return (((value + boundary - 1) / boundary) * boundary);
 }
 
-/* Output the form of location attributes suitable for whole variables and
-   whole parameters.  Note that the location attributes for struct fields
-   are generated by the routine `data_member_location_attribute' below.  */
+/* Given a pointer to what is assumed to be a FIELD_DECL node, return a
+   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.  */
 
-static void
-location_attribute (rtl)
-     register rtx rtl;
+static inline tree
+field_type (decl)
+     register tree decl;
 {
-  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
-  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+  register tree type;
 
-  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);
-  ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
-  ASM_OUTPUT_LABEL (asm_out_file, begin_label);
+  if (TREE_CODE (decl) == ERROR_MARK)
+    return integer_type_node;
 
-  /* Handle a special case.  If we are about to output a location descriptor
-     for a variable or parameter which has been optimized out of existence,
-     don't do that.  Instead we output a zero-length location descriptor
-     value as part of the location attribute.  Note that we cannot simply
-     suppress the entire location attribute, because the absence of a
-     location attribute in certain kinds of DIEs is used to indicate some-
-     thing entirely different... i.e. that the DIE represents an object
-     declaration, but not a definition.  So sayeth the PLSIG.  */
+  type = DECL_BIT_FIELD_TYPE (decl);
+  if (type == NULL)
+    type = TREE_TYPE (decl);
+  return type;
+}
 
-  if (! is_pseudo_reg (rtl))
-    output_loc_descriptor (eliminate_regs (rtl, 0, 0));
+/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE
+   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.  */
 
-  ASM_OUTPUT_LABEL (asm_out_file, end_label);
+static inline unsigned
+simple_type_align_in_bits (type)
+     register tree type;
+{
+  return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;
 }
 
-/* Output the specialized form of location attribute used for data members
-   of struct types.
+/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE
+   node, return the size in bits for the type if it is a constant, or
+   else return the alignment for the type if the type's size is not
+   constant, or else return BITS_PER_WORD if the type actually turns out
+   to be an ERROR_MARK node.  */
 
-   In the special case of a FIELD_DECL node which represents a bit-field,
-   the "offset" part of this special location descriptor must indicate the
-   distance in bytes from the lowest-addressed byte of the containing
-   struct or union type to the lowest-addressed byte of the "containing
-   object" for the bit-field.
+static inline unsigned
+simple_type_size_in_bits (type)
+     register tree type;
+{
+  if (TREE_CODE (type) == ERROR_MARK)
+    return BITS_PER_WORD;
+  else
+    {
+      register tree type_size_tree = TYPE_SIZE (type);
 
-   For any given bit-field, the "containing object" is a hypothetical
-   object (of some integral or enum type) within which the given bit-field
-   lives.  The type of this hypothetical "containing object" is always the
-   same as the declared type of the individual bit-field itself.
+      if (TREE_CODE (type_size_tree) != INTEGER_CST)
+       return TYPE_ALIGN (type);
 
-   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 the `byte_size_attribute' function below.)
-*/
+      return (unsigned) TREE_INT_CST_LOW (type_size_tree);
+    }
+}
 
+/* Given a pointer to what is assumed to be a FIELD_DECL node, compute and
+   return the byte offset of the lowest addressed byte of the "containing
+   object" for the given FIELD_DECL, or return 0 if we are unable to deter-
+   mine what that offset is, either because the argument turns out to be a
+   pointer to an ERROR_MARK node, or because the offset is actually variable.
+   (We can't handle the latter case just yet.)  */
 
-static void
-data_member_location_attribute (decl)
+static unsigned
+field_byte_offset (decl)
      register tree decl;
 {
-  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
-  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
   register unsigned type_align_in_bytes;
   register unsigned type_align_in_bits;
-  register unsigned offset_in_align_units;
-  register unsigned offset_in_bytes;
+  register unsigned type_size_in_bits;
+  register unsigned object_offset_in_align_units;
+  register unsigned object_offset_in_bits;
+  register unsigned object_offset_in_bytes;
   register tree type;
-  register tree bitpos_tree = DECL_FIELD_BITPOS (decl);
+  register tree bitpos_tree;
+  register tree field_size_tree;
   register unsigned bitpos_int;
+  register unsigned deepest_bitpos;
+  register unsigned field_size_in_bits;
 
   if (TREE_CODE (decl) == ERROR_MARK)
-    return;
+    return 0;
 
   if (TREE_CODE (decl) != FIELD_DECL)
     abort ();
 
-  /* The bit position given by DECL_FIELD_BITPOS could be non-constant
-     in the case where one or more variable sized members preceded this
-     member in the containing struct type.  We could probably correctly
-     handle this case someday, by it's too complicated to deal with at
-     the moment (and probably too rare to worry about), so just punt on
-     the whole AT_location attribute for now.  Eventually, we'll have
-     to analyze the expression given as the DECL_FIELD_BITPOS and turn
-     it into a member-style AT_location descriptor, but that'll be
-     tough to do.  -- rfg  */
+  type = field_type (decl);
+
+  bitpos_tree = DECL_FIELD_BITPOS (decl);
+  field_size_tree = DECL_SIZE (decl);
+
+  /* We cannot yet cope with fields whose positions or sizes are variable,
+     so for now, when we see such things, we simply return 0.  Someday,
+     we may be able to handle such cases, but it will be damn difficult.  */
 
   if (TREE_CODE (bitpos_tree) != INTEGER_CST)
-    return;
+    return 0;
   bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree);
 
-  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);
-  ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
-  ASM_OUTPUT_LABEL (asm_out_file, begin_label);
-  ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST);
+  if (TREE_CODE (field_size_tree) != INTEGER_CST)
+    return 0;
+  field_size_in_bits = (unsigned) TREE_INT_CST_LOW (field_size_tree);
 
-  type = DECL_BIT_FIELD_TYPE (decl);
-  if (type == NULL)
-    type = TREE_TYPE (decl);
+  type_size_in_bits = simple_type_size_in_bits (type);
 
-  type_align_in_bits = TYPE_ALIGN (type);
+  type_align_in_bits = simple_type_align_in_bits (type);
   type_align_in_bytes = type_align_in_bits / BITS_PER_UNIT;
 
-  /* WARNING!  Note that the GCC front-end doesn't make any attempt to
-     keep track of the starting bit offset (relative to the start of
-     the containing structure type) of the hypothetical "containing
-     object" for a bit-field.  (See the comments at the start of this
-     function.)  Thus, when computing the byte offset value for a
-     bit-field, all we can do is to divide the starting bit offset of
-     the bit-field by the alignment of the hypothetical "containing
-     object" (which we can easily find) and then multiply by the number
-     of bytes of that alignment.
-
-     This solution only yields an unambiguously correct result when
-     the size of the bit-field is strictly larger than the size of the
-     declared type minus the alignment of the declared type.  When this
-     condition is not satisfied, it means that there is at least an
-     "alignment unit's" worth of other slop which co-resides within the
-     hypothetical "containing object" with the bit field, and this other
-     slop could be either to the left of the bit-field or to the right
-     of the bit-field. (We have no way of knowing which.)
-
-     It also means that we cannot unambiguously tell exactly where the
-     hypothetical "containing object" begins within the containing struct
-     type.  We only know the precise position of the bit-field which is
-     contained therein, and that the hypothetical containing object must
-     be aligned as required for its type.  But when there is at least an
-     alignment unit's worth of slop co-resident in the containing object
-     with the actual bit-field, the actual start of the containing object
-     is ambiguous and thus, we cannot unambiguously determine the "correct"
-     byte offset to put into the AT_location attribute for the bit-field
-     itself.
-
-     This whole thing is a non-issue for the majority of targets, because
-     (for most GCC targets) the alignment of each supported integral type
-     is the same as the size of that type, and thus (size - alignment) for
-     the declared type of any bit-field yields zero, and the size (in bits)
-     of any bit-field must be bigger than zero, so there is never any
-     ambiguity about the starting positions of the containing objects of
-     bit-fields for most GCC targets.
-
-     An exception arises however for some machines (e.g. i386) which have
-     BIGGEST_ALIGNMENT set to something less than the size of type `long
-     long' (i.e. 64) and when we are confronted with something like:
+  /* Note that the GCC front-end doesn't make any attempt to keep track
+     of the starting bit offset (relative to the start of the containing
+     structure type) of the hypothetical "containing object" for a bit-
+     field.  Thus, when computing the byte offset value for the start of
+     the "containing object" of a bit-field, we must deduce this infor-
+     mation on our own.
+
+     This can be rather tricky to do in some cases.  For example, handling
+     the following structure type definition when compiling for an i386/i486
+     target (which only aligns long long's to 32-bit boundaries) can be very
+     tricky:
 
                struct S {
                        int             field1;
                        long long       field2:31;
                };
 
-     Here it is ambiguous (going by DWARF rules anyway) whether the con-
-     taining `long long' object for `field2' should be said to occupy the
-     first and second (32-bit) words of the containing struct type, or
-     whether it should be said to occupy the second and third words of
-     the struct type.
+     Fortunately, there is a simple rule-of-thumb which can be used in such
+     cases.  When compiling for an i386/i486, GCC will allocate 8 bytes for
+     the structure shown above.  It decides to do this based upon one simple
+     rule for bit-field allocation.  Quite simply, GCC allocates each "con-
+     taining object" for each bit-field at the first (i.e. lowest addressed)
+     legitimate alignment boundary (based upon the required minimum alignment
+     for the declared type of the field) which it can possibly use, subject
+     to the condition that there is still enough available space remaining
+     in the containing object (when allocated at the selected point) to
+     fully accommodate all of the bits of the bit-field itself.
+
+     This simple rule makes it obvious why GCC allocates 8 bytes for each
+     object of the structure type shown above.  When looking for a place to
+     allocate the "containing object" for `field2', the compiler simply tries
+     to allocate a 64-bit "containing object" at each successive 32-bit
+     boundary (starting at zero) until it finds a place to allocate that 64-
+     bit field such that at least 31 contiguous (and previously unallocated)
+     bits remain within that selected 64 bit field.  (As it turns out, for
+     the example above, the compiler finds that it is OK to allocate the
+     "containing object" 64-bit field at bit-offset zero within the
+     structure type.)
+
+     Here we attempt to work backwards from the limited set of facts we're
+     given, and we try to deduce from those facts, where GCC must have
+     believed that the containing object started (within the structure type).
+
+     The value we deduce is then used (by the callers of this routine) to
+     generate AT_location and AT_bit_offset attributes for fields (both
+     bit-fields and, in the case of AT_location, regular fields as well).
+  */
 
-     Currently, GCC allocates 8 bytes (for an i386 target) for each object
-     of the above type.  This is probably a bug however, and GCC should
-     probably be allocating 12 bytes for each such structure (for the i386
-     target).
+  /* Figure out the bit-distance from the start of the structure to the
+     "deepest" bit of the bit-field.  */
+  deepest_bitpos = bitpos_int + field_size_in_bits;
+
+  /* This is the tricky part.  Use some fancy footwork to deduce where the
+     lowest addressed bit of the containing object must be.  */
+  object_offset_in_bits
+    = ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits;
+
+  /* Compute the offset of the containing object in "alignment units".  */
+  object_offset_in_align_units = object_offset_in_bits / type_align_in_bits;
+
+  /* Compute the offset of the containing object in bytes.  */
+  object_offset_in_bytes = object_offset_in_align_units * type_align_in_bytes;
+
+  /* The above code assumes that the field does not cross an alignment
+     boundary.  This can happen if PCC_BITFIELD_TYPE_MATTERS is not defined,
+     or if the structure is packed.  If this happens, then we get an object
+     which starts after the bitfield, which means that the bit offset is
+     negative.  Gdb fails when given negative bit offsets.  We avoid this
+     by recomputing using the first bit of the bitfield.  This will give
+     us an object which does not completely contain the bitfield, but it
+     will be aligned, and it will contain the first bit of the bitfield.  */
+  if (object_offset_in_bits > bitpos_int)
+    {
+      deepest_bitpos = bitpos_int + 1;
+      object_offset_in_bits
+       = ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits;
+      object_offset_in_align_units = (object_offset_in_bits
+                                     / type_align_in_bits);
+      object_offset_in_bytes = (object_offset_in_align_units
+                               * type_align_in_bytes);
+    }
 
-     Assuming this bug gets fixed, one would have a strong case for saying
-     that the containing `long long' object for `field2' occupies the second
-     and third words of the above structure type, and that `field2' itself
-     occupies the first 31 bits of that containing object.  However consider:
+  return object_offset_in_bytes;
+}
 
-               struct S {
-                       int             field1;
-                       long long       field2:31;
-                       long long       field3:2;
-                       long long       field4:31;
-               };
+/****************************** attributes *********************************/
+
+/* The following routines are responsible for writing out the various types
+   of Dwarf attributes (and any following data bytes associated with them).
+   These routines are listed in order based on the numerical codes of their
+   associated attributes.  */
+
+/* Generate an AT_sibling attribute.  */
+
+static inline void
+sibling_attribute ()
+{
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_sibling);
+  sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
+  ASM_OUTPUT_DWARF_REF (asm_out_file, label);
+}
+
+/* Output the form of location attributes suitable for whole variables and
+   whole parameters.  Note that the location attributes for struct fields
+   are generated by the routine `data_member_location_attribute' below.  */
+
+static void
+location_attribute (rtl)
+     register rtx rtl;
+{
+  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
+  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  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);
+  ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
+  ASM_OUTPUT_LABEL (asm_out_file, begin_label);
 
-     Even if the current "member allocation" bug in GCC is fixed, this ex-
-     ample would still illustrate a case in which the starting point of the
-     containing `long long' object for `field4' would be ambiguous, even
-     though we know the exact starting bit offset (within the structure) of
-     the `field4' bit-field itself.
-
-     We essentially just ignore this whole issue here and always act as if
-     most of the slop which co-resides in a containing object along with a
-     bit-field appears in that containing object *AFTER* the bit field.
-     Thus, for the above example, we say that the containing object for
-     `field4' occupies the third and fourth words of the structure type,
-     even though objects of the type only occupy three words.  As long
-     as the debugger understands that the compiler uses this disambiguation
-     rule, the debugger should easily be able to do the Right Thing in all
-     cases.
+  /* Handle a special case.  If we are about to output a location descriptor
+     for a variable or parameter which has been optimized out of existence,
+     don't do that.  Instead we output a zero-length location descriptor
+     value as part of the location attribute.
+
+     A variable which has been optimized out of existence will have a
+     DECL_RTL value which denotes a pseudo-reg.
+
+     Currently, in some rare cases, variables can have DECL_RTL values
+     which look like (MEM (REG pseudo-reg#)).  These cases are due to
+     bugs elsewhere in the compiler.  We treat such cases
+     as if the variable(s) in question had been optimized out of existence.
+
+     Note that in all cases where we wish to express the fact that a
+     variable has been optimized out of existence, we do not simply
+     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 saith
+     the PLSIG.
   */
 
-  offset_in_align_units = bitpos_int / type_align_in_bits;
-  offset_in_bytes = offset_in_align_units * type_align_in_bytes;
+  if (! is_pseudo_reg (rtl)
+      && (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0))))
+    output_loc_descriptor (rtl);
+
+  ASM_OUTPUT_LABEL (asm_out_file, end_label);
+}
+
+/* Output the specialized form of location attribute used for data members
+   of struct and union types.
 
-  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, offset_in_bytes);
+   In the special case of a FIELD_DECL node which represents a bit-field,
+   the "offset" part of this special location descriptor must indicate the
+   distance in bytes from the lowest-addressed byte of the containing
+   struct or union type to the lowest-addressed byte of the "containing
+   object" for the bit-field.  (See the `field_byte_offset' function above.)
+
+   For any given bit-field, the "containing object" is a hypothetical
+   object (of some integral or enum type) within which the given bit-field
+   lives.  The type of this hypothetical "containing object" is always the
+   same as the declared type of the individual bit-field itself (for GCC
+   anyway... the DWARF spec doesn't actually mandate this).
+
+   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 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.)  */
+
+static void
+data_member_location_attribute (t)
+     register tree t;
+{
+  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);
+  ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
+  ASM_OUTPUT_LABEL (asm_out_file, begin_label);
+  ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST);
+  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, object_offset_in_bytes);
   ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADD);
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
@@ -1783,12 +2261,12 @@ const_value_attribute (rtl)
           simplicity we always just output CONST_DOUBLEs using 8 bytes.  */
 
        ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
-                               (unsigned) CONST_DOUBLE_HIGH (rtl),
-                               (unsigned) CONST_DOUBLE_LOW (rtl));
+                               (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (rtl),
+                               (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (rtl));
        break;
 
       case CONST_STRING:
-       ASM_OUTPUT_DWARF_STRING (asm_out_file, XSTR (rtl, 0));
+       ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, XSTR (rtl, 0));
        break;
 
       case SYMBOL_REF:
@@ -1812,6 +2290,9 @@ const_value_attribute (rtl)
           we just punt and generate an AT_const_value attribute with form
           FORM_BLOCK4 and a length of zero.  */
        break;
+
+      default:
+       abort ();  /* No other kinds of rtx should be possible here.  */
     }
 
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
@@ -1839,72 +2320,122 @@ 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 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;
 
+  rtl = eliminate_regs (rtl, 0, NULL_RTX);
+#ifdef LEAF_REG_REMAP
+  if (leaf_function)
+    leaf_renumber_regs_insn (rtl);
+#endif
+
   switch (GET_CODE (rtl))
     {
+    case ADDRESSOF:
+      /* The address of a variable that was optimized away; don't emit
+        anything.  */
+      break;
+
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_STRING:
@@ -1921,6 +2452,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.  */
     }
@@ -1929,18 +2469,18 @@ 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;
 {
   if (name_string && *name_string)
     {
       ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_name);
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, name_string);
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, name_string);
     }
 }
 
-inline void
+static inline void
 fund_type_attribute (ft_code)
      register unsigned ft_code;
 {
@@ -1968,7 +2508,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;
 {
@@ -2000,13 +2540,15 @@ mod_u_d_type_attribute (type, decl_const, decl_volatile)
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
 
-inline void
+#ifdef USE_ORDERING_ATTRIBUTE
+static inline void
 ordering_attribute (ordering)
      register unsigned ordering;
 {
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_ordering);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, ordering);
 }
+#endif /* defined(USE_ORDERING_ATTRIBUTE) */
 
 /* Note that the block of subscript information for an array type also
    includes information about the element type of type given array type.  */
@@ -2056,12 +2598,11 @@ 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,
-                                           TREE_CODE (lower) == INTEGER_CST,
-                                           TREE_CODE (upper) == INTEGER_CST));
+                 FMT_CODE (1, TREE_CODE (lower) == INTEGER_CST,
+                           (upper && TREE_CODE (upper) == INTEGER_CST)));
 
          /* Output the index type for this dimension.  */
 
@@ -2102,7 +2643,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);
 
@@ -2129,17 +2670,18 @@ byte_size_attribute (tree_node)
       case ENUMERAL_TYPE:
       case RECORD_TYPE:
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
+      case ARRAY_TYPE:
        size = int_size_in_bytes (tree_node);
        break;
 
       case FIELD_DECL:
        /* For a data member of a struct or union, the AT_byte_size is
-          always given as the number of bytes normally allocated for
+          generally given as the number of bytes normally allocated for
           an object of the *declared* type of the member itself.  This
           is true even for bit-fields.  */
-       size = int_size_in_bytes (DECL_BIT_FIELD_TYPE (tree_node)
-                                 ? DECL_BIT_FIELD_TYPE (tree_node)
-                                 : TREE_TYPE (tree_node));
+       size = simple_type_size_in_bits (field_type (tree_node))
+              / BITS_PER_UNIT;
        break;
 
       default:
@@ -2164,71 +2706,76 @@ byte_size_attribute (tree_node)
    lives.  The type of this hypothetical "containing object" is always the
    same as the declared type of the individual bit-field itself.
 
+   The determination of the exact location of the "containing object" for
+   a bit-field is rather complicated.  It's handled by the `field_byte_offset'
+   function (above).
+
    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;
 {
+  register unsigned object_offset_in_bytes = field_byte_offset (decl);
   register tree type = DECL_BIT_FIELD_TYPE (decl);
-  register unsigned dwarf_bit_offset;
   register tree bitpos_tree = DECL_FIELD_BITPOS (decl);
   register unsigned bitpos_int;
+  register unsigned highest_order_object_bit_offset;
+  register unsigned highest_order_field_bit_offset;
+  register unsigned bit_offset;
 
-  assert (TREE_CODE (decl) == FIELD_DECL);     /* Must be a field.  */
-  assert (type);                               /* Must be a bit field.  */
+  /* Must be a bit field.  */
+  if (!type
+      || TREE_CODE (decl) != FIELD_DECL)
+    abort ();
 
-  /* The bit position given by DECL_FIELD_BITPOS could be non-constant
-     in the case where one or more variable sized members preceded this
-     member in the containing struct type.  We could probably correctly
-     handle this case someday, by it's too complicated to deal with at
-     the moment, so just punt on the whole AT_bit_offset attribute for
-     now.  Eventually, we'll have to analyze the (variable) expression
-     given as the DECL_FIELD_BITPOS and see if we can factor out just
-     the (constant) bit offset part of that expression.  -- rfg  */
+  /* We can't yet handle bit-fields whose offsets are variable, so if we
+     encounter such things, just return without generating any attribute
+     whatsoever.  */
 
   if (TREE_CODE (bitpos_tree) != INTEGER_CST)
     return;
   bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree);
 
-  /* For a detailed description of how the AT_bit_offset attribute value
-     is calculated, see the comments in `data_member_location_attribute'
-     above.  */
+  /* Note that the bit offset is always the distance (in bits) from the
+     highest-order bit of the "containing object" to the highest-order
+     bit of the bit-field itself.  Since the "high-order end" of any
+     object or field is different on big-endian and little-endian machines,
+     the computation below must take account of these differences.  */
 
-#if (BYTES_BIG_ENDIAN == 1)
-  dwarf_bit_offset = bitpos_int % TYPE_ALIGN (type);
-#else
-  {
-    register unsigned high_order_bitpos
-      = bitpos_int + (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
-    register tree type_size_tree = TYPE_SIZE (type);
-    register unsigned type_size_in_bits;
+  highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT;
+  highest_order_field_bit_offset = bitpos_int;
 
-    if (TREE_CODE (type_size_tree) != INTEGER_CST)
-      abort ();
-    type_size_in_bits = (unsigned) TREE_INT_CST_LOW (type_size_tree);
+  if (! BYTES_BIG_ENDIAN)
+    {
+      highest_order_field_bit_offset
+       += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
 
-    dwarf_bit_offset = type_size_in_bits
-                       - (high_order_bitpos % TYPE_ALIGN (type));
-  }
-#endif
+      highest_order_object_bit_offset += simple_type_size_in_bits (type);
+    }
+
+  bit_offset =
+    (! 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, dwarf_bit_offset);
+  ASM_OUTPUT_DWARF_DATA2 (asm_out_file, bit_offset);
 }
 
 /* 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;
 {
-  assert (TREE_CODE (decl) == FIELD_DECL);     /* Must be a field.  */
-  assert (DECL_BIT_FIELD_TYPE (decl));         /* Must be a bit field.  */
+  /* Must be a field and a bit field.  */
+  if (TREE_CODE (decl) != FIELD_DECL
+      || ! DECL_BIT_FIELD_TYPE (decl))
+    abort ();
 
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_size);
   ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
@@ -2240,7 +2787,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;
 {
@@ -2266,7 +2813,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;
 {
@@ -2278,7 +2825,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;
 {
@@ -2289,7 +2836,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;
 {
@@ -2297,10 +2844,30 @@ high_pc_attribute (asm_high_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_high_label);
 }
 
+/* Generate an AT_body_begin attribute for a subroutine DIE.  */
+
+static inline void
+body_begin_attribute (asm_begin_label)
+     register char *asm_begin_label;
+{
+  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_begin);
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_begin_label);
+}
+
+/* Generate an AT_body_end attribute for a subroutine DIE.  */
+
+static inline void
+body_end_attribute (asm_end_label)
+     register char *asm_end_label;
+{
+  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_end);
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, 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;
 {
@@ -2308,7 +2875,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;
 {
@@ -2316,9 +2883,7 @@ member_attribute (context)
 
   /* Generate this attribute only for members in C++.  */
 
-  if (context != NULL
-      && (TREE_CODE (context) == RECORD_TYPE
-         || TREE_CODE (context) == UNION_TYPE))
+  if (context != NULL && is_tagged_type (context))
     {
       ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_member);
       sprintf (label, TYPE_NAME_FMT, TYPE_UID (context));
@@ -2326,7 +2891,8 @@ member_attribute (context)
     }
 }
 
-inline void
+#if 0
+static inline void
 string_length_attribute (upper_bound)
      register tree upper_bound;
 {
@@ -2341,16 +2907,17 @@ string_length_attribute (upper_bound)
   output_bound_representation (upper_bound, 0, 'u');
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
+#endif
 
-inline void
+static inline void
 comp_dir_attribute (dirname)
      register char *dirname;
 {
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_comp_dir);
-  ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+  ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, dirname);
 }
 
-inline void
+static inline void
 sf_names_attribute (sf_names_start_label)
      register char *sf_names_start_label;
 {
@@ -2359,7 +2926,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;
 {
@@ -2368,7 +2935,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;
 {
@@ -2377,7 +2944,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;
 {
@@ -2385,30 +2952,30 @@ prototyped_attribute (func_type)
       && (TYPE_ARG_TYPES (func_type) != NULL))
     {
       ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_prototyped);
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
     }
 }
 
-inline void
+static inline void
 producer_attribute (producer)
      register char *producer;
 {
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_producer);
-  ASM_OUTPUT_DWARF_STRING (asm_out_file, producer);
+  ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, producer);
 }
 
-inline void
+static inline void
 inline_attribute (decl)
      register tree decl;
 {
-  if (TREE_INLINE (decl))
+  if (DECL_INLINE (decl))
     {
       ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_inline);
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
     }
 }
 
-inline void
+static inline void
 containing_type_attribute (containing_type)
      register tree containing_type;
 {
@@ -2419,7 +2986,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;
 {
@@ -2444,7 +3011,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;
@@ -2455,17 +3022,19 @@ 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;
 {
   if (DECL_VIRTUAL_P (func_decl))
     {
+#if 0 /* DECL_ABSTRACT_VIRTUAL_P is C++-specific.  */
       if (DECL_ABSTRACT_VIRTUAL_P (func_decl))
         ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
       else
+#endif
         ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
     }
 }
 
@@ -2476,7 +3045,7 @@ pure_or_virtual_attribute (func_decl)
 /* Output an AT_name attribute and an AT_src_coords attribute for the
    given decl, but only if it actually has a name.  */
 
-inline void
+static void
 name_and_src_coords_attributes (decl)
     register tree decl;
 {
@@ -2492,7 +3061,7 @@ name_and_src_coords_attributes (decl)
        /* This is annoying, but we have to pop out of the .debug section
           for a moment while we call `lookup_filename' because calling it
           may cause a temporary switch into the .debug_sfnames section and
-          most svr4 assemblers are not smart enough be be able to nest
+          most svr4 assemblers are not smart enough to be able to nest
           section switches to any depth greater than one.  Note that we
           also can't skirt this issue by delaying all output to the
           .debug_sfnames section unit the end of compilation because that
@@ -2505,7 +3074,7 @@ name_and_src_coords_attributes (decl)
 
         src_coords_attribute (file_index, DECL_SOURCE_LINE (decl));
       }
-#endif
+#endif /* defined(DWARF_DECL_COORDINATES) */
     }
 }
 
@@ -2521,30 +3090,49 @@ 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));
 
   if (type_is_fundamental (root_type (type)))
-    if (root_type_modified)
+    {
+      if (root_type_modified)
        mod_fund_type_attribute (type, decl_const, decl_volatile);
-    else
+      else
        fund_type_attribute (fundamental_type_code (type));
+    }
   else
-    if (root_type_modified)
+    {
+      if (root_type_modified)
        mod_u_d_type_attribute (type, decl_const, decl_volatile);
-    else
-       user_def_type_attribute (type);
+      else
+       /* 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)
+          and that copy might have a different TYPE_UID from the original
+          ..._TYPE node.  (Note that when `equate_type_number_to_die_number'
+          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));
+    }
 }
 
 /* Given a tree pointer to a struct, class, union, or enum type node, return
@@ -2564,25 +3152,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);
@@ -2591,7 +3168,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.
@@ -2612,13 +3189,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;
 {
@@ -2627,6 +3204,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.  */
@@ -2653,9 +3252,9 @@ output_array_type_die (arg)
      we will only do so for multidimensional arrays.  After all, we don't
      want to waste space in the .debug section now do we?)  */
 
-#if 0
+#ifdef USE_ORDERING_ATTRIBUTE
   ordering_attribute (ORD_row_major);
-#endif
+#endif /* defined(USE_ORDERING_ATTRIBUTE) */
 
   subscript_data_attribute (type);
 }
@@ -2675,23 +3274,77 @@ 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;
 {
   register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
-  register tree return_type = TREE_TYPE (type);
+  register tree origin = decl_ultimate_origin (decl);
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_entry_point);
   sibling_attribute ();
   dienum_push ();
-  name_and_src_coords_attributes (decl);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (return_type, 0, 0);
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
+    {
+      name_and_src_coords_attributes (decl);
+      member_attribute (DECL_CONTEXT (decl));
+      type_attribute (TREE_TYPE (TREE_TYPE (decl)), 0, 0);
+    }
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
+  else
+    low_pc_attribute (function_start_label (decl));
 }
 #endif
 
+/* Output a DIE to represent an inlined instance of an enumeration type.  */
+
+static void
+output_inlined_enumeration_type_die (arg)
+     register void *arg;
+{
+  register tree type = arg;
+
+  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_enumeration_type);
+  sibling_attribute ();
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
+  abstract_origin_attribute (type);
+}
+
+/* Output a DIE to represent an inlined instance of a structure type.  */
+
+static void
+output_inlined_structure_type_die (arg)
+     register void *arg;
+{
+  register tree type = arg;
+
+  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_structure_type);
+  sibling_attribute ();
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
+  abstract_origin_attribute (type);
+}
+
+/* Output a DIE to represent an inlined instance of a union type.  */
+
+static void
+output_inlined_union_type_die (arg)
+     register void *arg;
+{
+  register tree type = arg;
+
+  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_union_type);
+  sibling_attribute ();
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
+  abstract_origin_attribute (type);
+}
+
 /* Output a DIE to represent an enumeration type.  Note that these DIEs
    include all of the information about the enumeration values also.
    This information is encoded into the element_list attribute.         */
@@ -2724,37 +3377,51 @@ output_enumeration_type_die (arg)
    function type.
 
    Note that this routine is a bit unusual because its argument may be
-   either a PARM_DECL node or else some sort of a ..._TYPE node.  If it's
-   the formar then this function is being called to output a real live
-   formal parameter declaration.  If it's the latter, then this function
-   is only being called to output a TAG_formal_parameter DIE to stand as
-   a placeholder for some formal argument type of some subprogram type.  */
+   a ..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which
+   represents an inlining of some PARM_DECL) or else some sort of a
+   ..._TYPE node.  If it's the former then this function is being called
+   to output a DIE to represent a formal parameter object (or some inlining
+   thereof).  If it's the latter, then this function is only being called
+   to output a TAG_formal_parameter DIE to stand as a placeholder for some
+   formal argument type of some subprogram type.  */
 
 static void
 output_formal_parameter_die (arg)
      register void *arg;
 {
-  register tree decl = arg;
-  register tree type;
-
-  if (TREE_CODE (decl) == PARM_DECL)
-    type = TREE_TYPE (decl);
-  else
-    {
-      type = decl;     /* we were called with a type, not a decl */
-      decl = NULL;
-    }
+  register tree node = arg;
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_formal_parameter);
   sibling_attribute ();
-  if (decl)
+
+  switch (TREE_CODE_CLASS (TREE_CODE (node)))
     {
-      name_and_src_coords_attributes (decl);
-      type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
-      location_or_const_value_attribute (decl);
+    case 'd':  /* We were called with some kind of a ..._DECL node.  */
+      {
+       register tree origin = decl_ultimate_origin (node);
+
+       if (origin != NULL)
+         abstract_origin_attribute (origin);
+       else
+         {
+           name_and_src_coords_attributes (node);
+           type_attribute (TREE_TYPE (node),
+                           TREE_READONLY (node), TREE_THIS_VOLATILE (node));
+         }
+       if (DECL_ABSTRACT (node))
+         equate_decl_number_to_die_number (node);
+       else
+         location_or_const_value_attribute (node);
+      }
+      break;
+
+    case 't':  /* We were called with some kind of a ..._TYPE node.  */
+      type_attribute (node, 0, 0);
+      break;
+
+    default:
+      abort ();        /* Should never happen.  */
     }
-  else
-    type_attribute (type, 0, 0);
 }
 
 /* Output a DIE to represent a declared function (either file-scope
@@ -2765,24 +3432,44 @@ output_global_subroutine_die (arg)
      register void *arg;
 {
   register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
-  register tree return_type = TREE_TYPE (type);
+  register tree origin = decl_ultimate_origin (decl);
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_subroutine);
   sibling_attribute ();
   dienum_push ();
-  name_and_src_coords_attributes (decl);
-  inline_attribute (decl);
-  prototyped_attribute (type);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (return_type, 0, 0);
-  if (!TREE_EXTERNAL (decl))
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
+    {
+      register tree type = TREE_TYPE (decl);
+
+      name_and_src_coords_attributes (decl);
+      inline_attribute (decl);
+      prototyped_attribute (type);
+      member_attribute (DECL_CONTEXT (decl));
+      type_attribute (TREE_TYPE (type), 0, 0);
+      pure_or_virtual_attribute (decl);
+    }
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
+  else
     {
-      char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+      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)));
-      sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number);
-      high_pc_attribute (func_end_label);
+         low_pc_attribute (function_start_label (decl));
+         sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+         high_pc_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);
+           }
+       }
     }
 }
 
@@ -2794,103 +3481,65 @@ output_global_variable_die (arg)
      register void *arg;
 {
   register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
+  register tree origin = decl_ultimate_origin (decl);
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_variable);
   sibling_attribute ();
-  name_and_src_coords_attributes (decl);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
-  if (!TREE_EXTERNAL (decl))
-    location_or_const_value_attribute (decl);
-}
-
-#if 0
-/* TAG_inline_subroutine has been retired by the UI/PLSIG.  We're
-   now supposed to use either TAG_subroutine or TAG_global_subroutine
-   (depending on whether or not the function in question has internal
-   or external linkage) and we're supposed to just put in an AT_inline
-   attribute.  */
-static void
-output_inline_subroutine_die (arg)
-     register void *arg;
-{
-  register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
-  register tree return_type = TREE_TYPE (type);
-
-  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inline_subroutine);
-  sibling_attribute ();
-  dienum_push ();
-  name_and_src_coords_attributes (decl);
-  prototyped_attribute (type);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (return_type, 0, 0);
-
-  /* Note:  For each inline function which gets an out-of-line body
-     generated for it, we want to generate AT_low_pc and AT_high_pc
-     attributes here for the function's out-of-line body.
-
-     Unfortunately, the decision as to whether or not to generate an
-     out-of-line body for any given inline function may not be made
-     until we reach the end of the containing scope for the given
-     inline function (because only then will it be known if the
-     function was ever even called).
-
-     For this reason, the output of DIEs representing file-scope inline
-     functions gets delayed until a special post-pass which happens only
-     after we have reached the end of the compilation unit.  Because of
-     this mechanism, we can always be sure (by the time we reach here)
-     that TREE_ASM_WRITTEN(decl) will correctly indicate whether or not
-     there was an out-of-line body generated for this inline function.
-  */
-
-  if (!TREE_EXTERNAL (decl))
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
     {
-      if (TREE_ASM_WRITTEN (decl))
-        {
-          char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-          low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
-          sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number);
-          high_pc_attribute (func_end_label);
-        }
+      name_and_src_coords_attributes (decl);
+      member_attribute (DECL_CONTEXT (decl));
+      type_attribute (TREE_TYPE (decl),
+                     TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
+    }
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
+  else
+    {
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && current_function_decl == decl_function_context (decl))
+       location_or_const_value_attribute (decl);
     }
 }
-#endif
 
 static void
 output_label_die (arg)
      register void *arg;
 {
   register tree decl = arg;
-  register rtx insn = DECL_RTL (decl);
+  register tree origin = decl_ultimate_origin (decl);
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_label);
   sibling_attribute ();
-  name_and_src_coords_attributes (decl);
-
-  /* When optimization is enabled (with -O) the code in jump.c and in flow.c
-     may cause insns representing one of more of the user's own labels to
-     be deleted.  This happens whenever it is determined that a given label
-     is unreachable.
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
+    name_and_src_coords_attributes (decl);
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
+  else
+    {
+      register rtx insn = DECL_RTL (decl);
 
-     In such cases, we here generate an abbreviated form of a label DIE.
-     This abbreviated version does *not* have a low_pc attribute.  This
-     should signify to the debugger that the label has been optimized away.
+      if (GET_CODE (insn) == CODE_LABEL)
+       {
+         char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-     Note that a CODE_LABEL can get deleted either by begin converted into
-     a NOTE_INSN_DELETED note, or by simply having its INSN_DELETED_P flag
-     set to true.  We handle both cases here.
-  */
+         /* When optimization is enabled (via -O) some parts of the compiler
+            (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which
+            represent source-level labels which were explicitly declared by
+            the user.  This really shouldn't be happening though, so catch
+            it if it ever does happen.  */
 
-  if (GET_CODE (insn) == CODE_LABEL && ! INSN_DELETED_P (insn))
-    {
-      char label[MAX_ARTIFICIAL_LABEL_BYTES];
+         if (INSN_DELETED_P (insn))
+           abort ();   /* Should never happen.  */
 
-      sprintf (label, INSN_LABEL_FMT, current_funcdef_number,
-                                     (unsigned) INSN_UID (insn));
-      low_pc_attribute (label);
+         sprintf (label, INSN_LABEL_FMT, current_funcdef_number,
+                                         (unsigned) INSN_UID (insn));
+         low_pc_attribute (label);
+       }
     }
 }
 
@@ -2899,16 +3548,20 @@ output_lexical_block_die (arg)
      register void *arg;
 {
   register tree stmt = arg;
-  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
-  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_lexical_block);
   sibling_attribute ();
   dienum_push ();
-  sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number);
-  low_pc_attribute (begin_label);
-  sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number);
-  high_pc_attribute (end_label);
+  if (! BLOCK_ABSTRACT (stmt))
+    {
+      char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
+      char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+      sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number);
+      low_pc_attribute (begin_label);
+      sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number);
+      high_pc_attribute (end_label);
+    }
 }
 
 static void
@@ -2916,16 +3569,21 @@ output_inlined_subroutine_die (arg)
      register void *arg;
 {
   register tree stmt = arg;
-  char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
-  char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inlined_subroutine);
   sibling_attribute ();
   dienum_push ();
-  sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number);
-  low_pc_attribute (begin_label);
-  sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number);
-  high_pc_attribute (end_label);
+  abstract_origin_attribute (block_ultimate_origin (stmt));
+  if (! BLOCK_ABSTRACT (stmt))
+    {
+      char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
+      char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+      sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number);
+      low_pc_attribute (begin_label);
+      sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number);
+      high_pc_attribute (end_label);
+    }
 }
 
 /* Output a DIE to represent a declared data object (either file-scope
@@ -2936,14 +3594,23 @@ output_local_variable_die (arg)
      register void *arg;
 {
   register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
+  register tree origin = decl_ultimate_origin (decl);
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_local_variable);
   sibling_attribute ();
-  name_and_src_coords_attributes (decl);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
-  location_or_const_value_attribute (decl);
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
+    {
+      name_and_src_coords_attributes (decl);
+      member_attribute (DECL_CONTEXT (decl));
+      type_attribute (TREE_TYPE (decl),
+                     TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
+    }
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
+  else
+    location_or_const_value_attribute (decl);
 }
 
 static void
@@ -2958,7 +3625,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);
@@ -2968,17 +3635,12 @@ output_member_die (arg)
 }
 
 #if 0
-/* Don't generate either pointer_type DIEs or reference_type DIEs.  According
-   to the 4-4-90 Dwarf draft spec (just after requirement #47):
-
-       These two type entries are not currently generated by any compiler.
-       Since the only way to name a pointer (or reference) type is C or C++
-       is via a "typedef", an entry with the "typedef" tag is generated
-       instead.
+/* 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)
@@ -3007,6 +3669,7 @@ output_reference_type_die (arg)
 }
 #endif
 
+static void
 output_ptr_to_mbr_type_die (arg)
      register void *arg;
 {
@@ -3040,6 +3703,12 @@ 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 (strcmp (language_string, "GNU Pascal") == 0)
+    language_attribute (LANG_PASCAL83);
   else if (flag_traditional)
     language_attribute (LANG_C);
   else
@@ -3056,7 +3725,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);
@@ -3073,13 +3742,38 @@ output_string_type_die (arg)
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_string_type);
   sibling_attribute ();
+  equate_type_number_to_die_number (type);
   member_attribute (TYPE_CONTEXT (type));
+  /* this is a fixed length string */
+  byte_size_attribute (type);
+}
 
-  /* Fudge the string length attribute for now.  */
+static void
+output_inheritance_die (arg)
+     register void *arg;
+{
+  register tree binfo = arg;
 
-  string_length_attribute (
-       TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
-}
+  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_NEWLINE (asm_out_file, "");
+    }
+  if (TREE_VIA_PUBLIC (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
+    }
+  else if (TREE_VIA_PROTECTED (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
+    }
+}  
 
 static void
 output_structure_type_die (arg)
@@ -3114,27 +3808,45 @@ output_local_subroutine_die (arg)
      register void *arg;
 {
   register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
-  register tree return_type = TREE_TYPE (type);
-  char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_subroutine);
-  sibling_attribute ();
-  dienum_push ();
-  name_and_src_coords_attributes (decl);
-  inline_attribute (decl);
-  prototyped_attribute (type);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (return_type, 0, 0);
+  register tree origin = decl_ultimate_origin (decl);
 
-  /* Avoid getting screwed up in cases where a function was declared static
-     but where no definition was ever given for it.  */
+  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_subroutine);
+  sibling_attribute ();
+  dienum_push ();
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
+    {
+      register tree type = TREE_TYPE (decl);
 
-  if (TREE_ASM_WRITTEN (decl))
+      name_and_src_coords_attributes (decl);
+      inline_attribute (decl);
+      prototyped_attribute (type);
+      member_attribute (DECL_CONTEXT (decl));
+      type_attribute (TREE_TYPE (type), 0, 0);
+      pure_or_virtual_attribute (decl);
+    }
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
+  else
     {
-      low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
-      sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number);
-      high_pc_attribute (func_end_label);
+      /* Avoid getting screwed up in cases where a function was declared
+        static but where no definition was ever given for it.  */
+
+      if (TREE_ASM_WRITTEN (decl))
+       {
+         char label[MAX_ARTIFICIAL_LABEL_BYTES];
+         low_pc_attribute (function_start_label (decl));
+         sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+         high_pc_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);
+           }
+       }
     }
 }
 
@@ -3159,13 +3871,21 @@ output_typedef_die (arg)
      register void *arg;
 {
   register tree decl = arg;
-  register tree type = TREE_TYPE (decl);
+  register tree origin = decl_ultimate_origin (decl);
 
   ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_typedef);
   sibling_attribute ();
-  name_and_src_coords_attributes (decl);
-  member_attribute (DECL_CONTEXT (decl));
-  type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
+  if (origin != NULL)
+    abstract_origin_attribute (origin);
+  else
+    {
+      name_and_src_coords_attributes (decl);
+      member_attribute (DECL_CONTEXT (decl));
+      type_attribute (TREE_TYPE (decl),
+                     TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
+    }
+  if (DECL_ABSTRACT (decl))
+    equate_decl_number_to_die_number (decl);
 }
 
 static void
@@ -3224,7 +3944,7 @@ output_unspecified_parameters_die (arg)
 
 static void
 output_padded_null_die (arg)
-     register void *arg;
+     register void *arg ATTRIBUTE_UNUSED;
 {
   ASM_OUTPUT_ALIGN (asm_out_file, 2);  /* 2**2 == 4 */
 }
@@ -3239,7 +3959,7 @@ output_padded_null_die (arg)
 
 static void
 output_die (die_specific_output_function, param)
-     register void (*die_specific_output_function)();
+     register void (*die_specific_output_function) PROTO ((void *));
      register void *param;
 {
   char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -3295,20 +4015,26 @@ 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)
      register tree function_or_method_type;
 {
   register tree link;
-  register tree formal_type;
+  register tree formal_type = NULL;
   register tree first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
 
+  /* Set TREE_ASM_WRITTEN while processing the parameters, lest we
+     get bogus recursion when outputting tagged types local to a
+     function declaration.  */
+  int save_asm_written = TREE_ASM_WRITTEN (function_or_method_type);
+  TREE_ASM_WRITTEN (function_or_method_type) = 1;
+
   /* In the case where we are generating a formal types list for a C++
      non-static member function type, skip over the first thing on the
      TYPE_ARG_TYPES list because it only represents the type of the
@@ -3354,6 +4080,8 @@ output_formal_types (function_or_method_type)
 
       output_type (formal_type, function_or_method_type);
     }
+
+  TREE_ASM_WRITTEN (function_or_method_type) = save_asm_written;
 }
 \f
 /* Remember a type in the pending_types_list.  */
@@ -3380,32 +4108,22 @@ pend_type (type)
 
 /* Return non-zero if it is legitimate to output DIEs to represent a
    given type while we are generating the list of child DIEs for some
-   DIE associated with a given scope.
-
-   This function returns non-zero if *either* of the following two conditions
-   is satisfied:
-
-        o      the type actually belongs to the given scope (as evidenced
-               by its TYPE_CONTEXT value), or
-
-        o      the type is anonymous, and the `scope' in question is *not*
-               a RECORD_TYPE or UNION_TYPE.
+   DIE (e.g. a function or lexical block DIE) associated with a given scope.
 
-   In theory, we should be able to generate DIEs for anonymous types
-   *anywhere* (since the scope of an anonymous type is irrelevant)
-   however svr4 SDB doesn't want to see other type DIEs within the
-   lists of child DIEs for a TAG_structure_type or TAG_union_type DIE.
+   See the comments within the function for a description of when it is
+   considered legitimate to output DIEs for various kinds of types.
 
    Note that TYPE_CONTEXT(type) may be NULL (to indicate global scope)
    or it may point to a BLOCK node (for types local to a block), or to a
    FUNCTION_DECL node (for types local to the heading of some function
    definition), or to a FUNCTION_TYPE node (for types local to the
    prototyped parameter list of a function type specification), or to a
-   RECORD_TYPE or UNION_TYPE node (in the case of C++ nested types).
+   RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node
+   (in the case of C++ nested types).
 
    The `scope' parameter should likewise be NULL or should point to a
    BLOCK node, a FUNCTION_DECL node, a FUNCTION_TYPE node, a RECORD_TYPE
-   node, or a UNION_TYPE node.
+   node, a UNION_TYPE node, or a QUAL_UNION_TYPE node.
 
    This function is used only for deciding when to "pend" and when to
    "un-pend" types to/from the pending_types_list.
@@ -3416,28 +4134,42 @@ pend_type (type)
    It order to delay the production of DIEs representing types of formal
    parameters, callers of this function supply `fake_containing_scope' as
    the `scope' parameter to this function.  Given that fake_containing_scope
-   is *not* the containing scope for *any* other type, the desired effect
-   is achieved, i.e. output of DIEs representing types is temporarily
-   suspended, and any type DIEs which would have been output otherwise
-   are instead placed onto the pending_types_list.  Later on, we can force
-   these (temporarily pended) types to be output simply by calling
+   is a tagged type which is *not* the containing scope for *any* other type,
+   the desired effect is achieved, i.e. output of DIEs representing types
+   is temporarily suspended, and any type DIEs which would have otherwise
+   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.  */
 
-static int
+static inline int
 type_ok_for_scope (type, scope)
     register tree type;
     register tree scope;
 {
-  return (TYPE_CONTEXT (type) == scope
-         || (TYPE_NAME (type) == NULL
-             && TREE_CODE (scope) != RECORD_TYPE
-             && TREE_CODE (scope) != UNION_TYPE));
+  /* Tagged types (i.e. struct, union, and enum types) must always be
+     output only in the scopes where they actually belong (or else the
+     scoping of their own tag names and the scoping of their member
+     names will be incorrect).  Non-tagged-types on the other hand can
+     generally be output anywhere, except that svr4 SDB really doesn't
+     want to see them nested within struct or union types, so here we
+     say it is always OK to immediately output any such a (non-tagged)
+     type, so long as we are not within such a context.  Note that the
+     only kinds of non-tagged types which we will be dealing with here
+     (for C and C++ anyway) will be array types and function types.  */
+
+  return is_tagged_type (type)
+        ? (TYPE_CONTEXT (type) == scope
+           /* Ignore namespaces for the moment.  */
+           || (scope == NULL_TREE
+               && TREE_CODE (TYPE_CONTEXT (type)) == NAMESPACE_DECL)
+           || (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
+               && TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
+        : (scope == NULL_TREE || ! is_tagged_type (scope));
 }
 
 /* Output any pending types (from the pending_types list) which we can output
-   now (given the limitations of the scope that we are working on now).
+   now (taking into account the scope that we are working on now).
 
    For each type output, remove the given type from the pending_types_list
    *before* we try to output it.
@@ -3445,8 +4177,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)
@@ -3493,13 +4224,39 @@ output_type (type, containing_scope)
     return;
 
   /* We are going to output a DIE to represent the unqualified version of
-     of this type (i.e. without any const or volatile qualifiers) so get
+     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 (finalizing && AGGREGATE_TYPE_P (type))
+       {
+         register tree member;
+
+         /* Some of our nested types might not have been defined when we
+            were written out before; force them out now.  */
+
+         for (member = TYPE_FIELDS (type); member;
+              member = TREE_CHAIN (member))
+           if (TREE_CODE (member) == TYPE_DECL
+               && ! TREE_ASM_WRITTEN (TREE_TYPE (member)))
+             output_type (TREE_TYPE (member), containing_scope);
+       }
+      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).  */
@@ -3517,8 +4274,11 @@ 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 that "basis" type.  */
+          (or a set of DIEs) to represent the "basis" type.  */
        output_type (TREE_TYPE (type), containing_scope);
        break;
 
@@ -3534,7 +4294,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;
 
@@ -3543,11 +4303,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);
@@ -3564,31 +4319,38 @@ 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:
       case RECORD_TYPE:
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
 
        /* For a non-file-scope tagged type, we can always go ahead and
           output a Dwarf description of this type right now, even if
           the type in question is still incomplete, because if this
           local type *was* ever completed anywhere within its scope,
           that complete definition would already have been attached to
-          this RECORD_TYPE, UNION_TYPE or ENUMERAL_TYPE node by the
-          time we reach this point.  That's true because of the way the
-          front-end does its processing of file-scope declarations (of
+          this RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ENUMERAL_TYPE
+          node by the time we reach this point.  That's true because of the
+          way the front-end does its processing of file-scope declarations (of
           functions and class types) within which other types might be
           nested.  The C and C++ front-ends always gobble up such "local
           scope" things en-mass before they try to output *any* debugging
@@ -3609,10 +4371,14 @@ 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.
-       */
-
-       if (TYPE_SIZE (type) == 0 && TYPE_CONTEXT (type) == NULL && !finalizing)
+          scope tagged types.  */
+
+       if (TYPE_SIZE (type) == 0
+           && (TYPE_CONTEXT (type) == NULL
+               || (TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+                   && TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_TYPE
+                   && TREE_CODE (TYPE_CONTEXT (type)) != METHOD_TYPE))
+           && !finalizing)
          return;       /* EARLY EXIT!  Avoid setting TREE_ASM_WRITTEN.  */
 
        /* Prevent infinite recursion in cases where the type of some
@@ -3633,8 +4399,12 @@ output_type (type, containing_scope)
            break;
 
          case UNION_TYPE:
+         case QUAL_UNION_TYPE:
            output_die (output_union_type_die, type);
            break;
+
+         default:
+           abort ();   /* Should never happen.  */
          }
 
        /* If this is not an incomplete type, output descriptions of
@@ -3656,10 +4426,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;
@@ -3668,32 +4451,24 @@ 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.  */
+
+           output_pending_types_for_scope (type);
+
            end_sibling_chain ();       /* Terminate member chain.  */
          }
 
@@ -3716,41 +4491,117 @@ output_type (type, containing_scope)
 
   TREE_ASM_WRITTEN (type) = 1;
 }
+
+static void
+output_tagged_type_instantiation (type)
+     register tree type;
+{
+  if (type == 0 || type == error_mark_node)
+    return;
+
+  /* We are going to output a DIE to represent the unqualified version of
+     this type (i.e. without any const or volatile qualifiers) so make
+     sure that we have the main variant (i.e. the unqualified version) of
+     this type now.  */
+
+  if (type != type_main_variant (type))
+    abort ();
+
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
+
+  switch (TREE_CODE (type))
+    {
+      case ERROR_MARK:
+       break;
+
+      case ENUMERAL_TYPE:
+       output_die (output_inlined_enumeration_type_die, type);
+       break;
+
+      case RECORD_TYPE:
+       output_die (output_inlined_structure_type_die, type);
+       break;
+
+      case UNION_TYPE:
+      case QUAL_UNION_TYPE:
+       output_die (output_inlined_union_type_die, type);
+       break;
+
+      default:
+       abort ();       /* Should never happen.  */
+    }
+}
 \f
 /* Output a TAG_lexical_block DIE followed by DIEs to represent all of
    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 have_significant_locals = 0;
+  register int must_output_die = 0;
+  register tree origin;
+  register enum tree_code origin_code;
 
   /* Ignore blocks never really used to make RTL.  */
 
   if (! stmt || ! TREE_USED (stmt))
     return;
 
-  /* Determine if this block contains any "significant" local declarations
-     which we need to output DIEs for.  */
+  /* Determine the "ultimate origin" of this block.  This block may be an
+     inlined instance of an inlined instance of inline function, so we
+     have to trace all of the way back through the origin chain to find
+     out what sort of node actually served as the original seed for the
+     creation of the current block.  */
 
-  if (BLOCK_INLINE_FUNCTION (stmt))
-    /* The outer scopes for inlinings *must* always be represented.  */
-    have_significant_locals = 1;
-  else
-    if (debug_info_level > DINFO_LEVEL_TERSE)
-      have_significant_locals = (BLOCK_VARS (stmt) != NULL);
-    else
-      {
-        register tree decl;
+  origin = block_ultimate_origin (stmt);
+  origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK;
 
-       for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl))
-         if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+  /* Determine if we need to output any Dwarf DIEs at all to represent this
+     block.  */
+
+  if (origin_code == FUNCTION_DECL)
+    /* The outer scopes for inlinings *must* always be represented.  We
+       generate TAG_inlined_subroutine DIEs for them.  (See below.)  */
+    must_output_die = 1;
+  else
+    {
+      /* In the case where the current block represents an inlining of the
+        "body block" of an inline function, we must *NOT* output any DIE
+        for this block because we have already output a DIE to represent
+        the whole inlined function scope and the "body block" of any
+        function doesn't really represent a different scope according to
+        ANSI C rules.  So we check here to make sure that this block does
+        not represent a "body block inlining" before trying to set the
+        `must_output_die' flag.  */
+
+      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.  */
+
+         if (debug_info_level > DINFO_LEVEL_TERSE)
+           /* We are not in terse mode so *any* local declaration counts
+              as being a "significant" one.  */
+           must_output_die = (BLOCK_VARS (stmt) != NULL);
+         else
            {
-             have_significant_locals = 1;
-             break;
+             register tree decl;
+
+             /* We are in terse mode, so only local (nested) function
+                definitions count as "significant" local declarations.  */
+
+             for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl))
+               if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+                 {
+                   must_output_die = 1;
+                   break;
+                 }
            }
-      }
+       }
+    }
 
   /* It would be a waste of space to generate a Dwarf TAG_lexical_block
      DIE for any block which contains no significant local declarations
@@ -3760,32 +4611,36 @@ output_block (stmt)
      a "significant" local declaration gets restricted to include only
      inlined function instances and local (nested) function definitions.  */
 
-  if (have_significant_locals)
+  if (origin_code == FUNCTION_DECL && BLOCK_ABSTRACT (stmt))
+    /* We don't care about an abstract inlined subroutine.  */;
+  else if (must_output_die)
     {
-      output_die (BLOCK_INLINE_FUNCTION (stmt)
-                       ? output_inlined_subroutine_die
-                       : output_lexical_block_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;
 
-  next_block_number++;
+  if (! BLOCK_ABSTRACT (stmt) && depth > 0)
+    next_block_number++;
 
   /* Output the DIEs to represent all of the data objects, functions,
      typedefs, and tagged types declared directly within this block
@@ -3809,10 +4664,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 static 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
@@ -3820,13 +4693,30 @@ output_decl (decl, containing_scope)
      register tree decl;
      register tree containing_scope;
 {
+  /* Make a note of the decl node we are going to be working on.  We may
+     need to give the user the source coordinates of where it appeared in
+     case we notice (later on) that something about it looks screwy.  */
+
+  dwarf_last_decl = decl;
+
   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
-     the labels we will reference in subsequent AT_low_pc and AT_high_pc
+     labels we will reference in subsequent AT_low_pc and AT_high_pc
      attributes (for subsequent blocks).  */
 
   if (DECL_IGNORED_P (decl) && TREE_CODE (decl) != FUNCTION_DECL)
@@ -3841,11 +4731,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 (TREE_EXTERNAL (decl))
+      if (DECL_INITIAL (decl) == NULL_TREE)
 #if (DWARF_VERSION > 1)
        if (debug_info_level <= DINFO_LEVEL_TERSE)
 #endif
@@ -3856,6 +4746,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
@@ -3872,7 +4769,7 @@ output_decl (decl, containing_scope)
 
       /* Now output a DIE to represent the function itself.  */
 
-      output_die (TREE_PUBLIC (decl) || TREE_EXTERNAL (decl)
+      output_die (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)
                                ? output_global_subroutine_die
                                : output_local_subroutine_die,
                  decl);
@@ -3888,183 +4785,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 (TREE_EXTERNAL (decl))
+      if (decl != current_function_decl || in_class)
        output_formal_types (TREE_TYPE (decl));
       else
        {
-         register tree arg_decls = DECL_ARGUMENTS (decl);
-
-         /* In the case where the FUNCTION_DECL represents a C++ non-static
-            member function, skip over the first thing on the DECL_ARGUMENTS
-            chain.  It only represents the hidden `this pointer' parameter
-            and the debugger should know implicitly that non-static member
-            functions have such a thing, and should be able to figure out
-            exactly what the type of each `this pointer' is (from the
-            AT_member attribute of the parent TAG_subroutine DIE)  without
-            being explicitly told.  */
+         /* Generate DIEs to represent all known formal parameters */
 
-         if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-           arg_decls = TREE_CHAIN (arg_decls);
-
-         {
-           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 the body of 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 get declared.  Just within
-              this contour, there will be another (nested) BLOCK which
-              represents the function's outermost block.  We don't want
-              to generate a lexical_block DIE to represent the outermost
-              block of a function body, 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 and
-              for Dwarf, we do not generate a TAG_lexical_block DIE for
-              that scope.  We must however see to it that the LABEL_DECLs
-              associated with `outer_scope' get DIEs generated for them.  */
+           register tree outer_scope = DECL_INITIAL (decl);
 
-           {
-             register tree label;
-
-             for (label = BLOCK_VARS (outer_scope);
-                  label;
-                  label = TREE_CHAIN (label))
-               output_decl (label, outer_scope);
-           }
-
-           output_decls_for_scope (BLOCK_SUBBLOCKS (outer_scope));
-
-           /* 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.  */
@@ -4081,22 +4934,27 @@ 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;
 
-      output_type (TREE_TYPE (decl), containing_scope);
+      /* 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.  */
 
-      /* 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 (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
+       {
+         output_tagged_type_instantiation (TREE_TYPE (decl));
+         return;
+       }
+
+      output_type (TREE_TYPE (decl), containing_scope);
 
-      if (DECL_NAME (decl))
+      if (! is_redundant_typedef (decl))
        /* Output a DIE to represent the typedef itself.  */
        output_die (output_typedef_die, decl);
       break;
@@ -4111,7 +4969,7 @@ output_decl (decl, containing_scope)
         generated any DIEs to represent mere external object declarations.  */
 
 #if (DWARF_VERSION <= 1)
-      if (TREE_EXTERNAL (decl) && ! TREE_PUBLIC (decl))
+      if (DECL_EXTERNAL (decl) && ! TREE_PUBLIC (decl))
        break;
 #endif
 
@@ -4126,13 +4984,20 @@ 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
         was already generated in the .debug_pubnames section sub-entry
         for this data object definition.  */
 
-      if (TREE_PUBLIC (decl))
+      if (TREE_PUBLIC (decl) && ! DECL_ABSTRACT (decl))
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
@@ -4140,11 +5005,26 @@ output_decl (decl, containing_scope)
          ASM_OUTPUT_LABEL (asm_out_file, label);
        }
 
-      /* Now output the DIE to represent the data object itself.  */
+      /* Now output the DIE to represent the data object itself.  This gets
+        complicated because of the possibility that the VAR_DECL really
+        represents an inlined instance of a formal parameter for an inline
+        function.  */
 
-      output_die (TREE_PUBLIC (decl) || TREE_EXTERNAL (decl)
-                  ? output_global_variable_die : output_local_variable_die,
-                 decl);
+      {
+        register void (*func) PROTO((void *));
+       register tree origin = decl_ultimate_origin (decl);
+
+       if (origin != NULL && TREE_CODE (origin) == PARM_DECL)
+         func = output_formal_parameter_die;
+       else
+         {
+           if (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+             func = output_global_variable_die;
+           else
+             func = output_local_variable_die;
+         }
+       output_die (func, decl);
+      }
       break;
 
     case FIELD_DECL:
@@ -4183,7 +5063,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
      gotta hope that the node in question doesn't represent a function
      definition.  If it does, then totally ignoring it is bound to screw
      up our count of blocks, and that it turn will completely screw up the
-     the labels we will reference in subsequent AT_low_pc and AT_high_pc
+     labels we will reference in subsequent AT_low_pc and AT_high_pc
      attributes (for subsequent blocks).  (It's too bad that BLOCK nodes
      don't carry their own sequence numbers with them!)  */
 
@@ -4202,23 +5082,45 @@ dwarfout_file_scope_decl (decl, set_finalizing)
         a builtin function.  Explicit programmer-supplied declarations of
         these same functions should NOT be ignored however.  */
 
-      if (TREE_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl))
+      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 (TREE_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) && ! TREE_EXTERNAL (decl))
+      if (TREE_PUBLIC (decl)
+         && ! DECL_EXTERNAL (decl)
+         && ! DECL_ABSTRACT (decl))
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
@@ -4229,7 +5131,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
          ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
          sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number);
          ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
-         ASM_OUTPUT_DWARF_STRING (asm_out_file,
+         ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
                                   IDENTIFIER_POINTER (DECL_NAME (decl)));
          ASM_OUTPUT_POP_SECTION (asm_out_file);
        }
@@ -4248,12 +5150,13 @@ dwarfout_file_scope_decl (decl, set_finalizing)
         lookup mechanism and cause it to miss things which really ought
         to be in scope at a given point.  */
 
-      if (TREE_EXTERNAL (decl) && !TREE_USED (decl))
+      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
        return;
 
       if (TREE_PUBLIC (decl)
-         && ! TREE_EXTERNAL (decl)
-         && GET_CODE (DECL_RTL (decl)) == MEM)
+         && ! DECL_EXTERNAL (decl)
+         && GET_CODE (DECL_RTL (decl)) == MEM
+         && ! DECL_ABSTRACT (decl))
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
@@ -4266,7 +5169,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
              ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
              sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number);
              ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
-             ASM_OUTPUT_DWARF_STRING (asm_out_file,
+             ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
                                       IDENTIFIER_POINTER (DECL_NAME (decl)));
              ASM_OUTPUT_POP_SECTION (asm_out_file);
            }
@@ -4295,9 +5198,28 @@ dwarfout_file_scope_decl (decl, set_finalizing)
       break;
 
     case TYPE_DECL:
-      /* Don't generate any DIEs to represent the standard built-in types.  */
-
-      if (DECL_SOURCE_LINE (decl) == 0)
+      /* Don't bother trying to generate any DIEs to represent any of the
+        normal built-in types for the language we are compiling, except
+        in cases where the types in question are *not* DWARF fundamental
+        types.  We make an exception in the case of non-fundamental types
+        for the sake of objective C (and perhaps C++) because the GNU
+        front-ends for these languages may in fact create certain "built-in"
+        types which are (for example) RECORD_TYPEs.  In such cases, we
+        really need to output these (non-fundamental) types because other
+        DIEs may contain references to them.  */
+
+      /* Also ignore language dependent types here, because they are probably
+        also built-in types.  If we didn't ignore them, then we would get
+        references to undefined labels because output_type doesn't support
+        them.   So, for now, we need to ignore them to avoid assembler
+        errors.  */
+
+      /* ??? This code is different than the equivalent code in dwarf2out.c.
+        The dwarf2out.c code is probably more correct.  */
+
+      if (DECL_SOURCE_LINE (decl) == 0
+         && (type_is_fundamental (TREE_TYPE (decl))
+             || TREE_CODE (TREE_TYPE (decl)) == LANG_TYPE))
        return;
 
       /* If we are in terse mode, don't generate any DIEs to represent
@@ -4307,7 +5229,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
         a return type or a formal parameter type of some function.  */
 
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-       if (DECL_NAME (decl) != NULL
+       if (! TYPE_DECL_IS_STUB (decl)
            || ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
           return;
 
@@ -4320,7 +5242,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
   finalizing = set_finalizing;
-  output_decl (decl, NULL);
+  output_decl (decl, NULL_TREE);
 
   /* NOTE:  The call above to `output_decl' may have caused one or more
      file-scope named types (i.e. tagged types) to be placed onto the
@@ -4333,11 +5255,18 @@ dwarfout_file_scope_decl (decl, set_finalizing)
      `output_pending_types_for_scope' takes them off of the list and un-sets
      their TREE_ASM_WRITTEN flags.  */
 
-  output_pending_types_for_scope (NULL);
+  output_pending_types_for_scope (NULL_TREE);
 
-  /* The above call should have totally emptied the pending_types_list.  */
-
-  assert (pending_types == 0);
+  /* The above call should have totally emptied the pending_types_list
+     if this is not a nested function or class.  If this is a nested type,
+     then the remaining pending_types will be emitted when the containing type
+     is handled.  */
+  
+  if (! DECL_CONTEXT (decl))
+    {
+      if (pending_types != 0)
+       abort ();
+    }
 
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
@@ -4354,7 +5283,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);
 }
@@ -4368,7 +5297,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);
 }
@@ -4384,13 +5313,44 @@ 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);
     }
 }
 
+/* Output a marker (i.e. a label) for the point in the generated code where
+   the real body of the function begins (after parameters have been moved
+   to their home locations).  */
+
+void
+dwarfout_begin_function ()
+{
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  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);
+}
+
+/* Output a marker (i.e. a label) for the point in the generated code where
+   the real body of the function ends (just before the epilogue code).  */
+
+void
+dwarfout_end_function ()
+{
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  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);
+}
+
 /* Output a marker (i.e. a label) for the absolute end of the generated code
    for a function definition.  This gets called *after* the epilogue code
    has been generated. */
@@ -4442,7 +5402,7 @@ generate_new_sfname_entry ()
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
   sprintf (label, SFNAMES_ENTRY_LABEL_FMT, filename_table[0].number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
-  ASM_OUTPUT_DWARF_STRING (asm_out_file,
+  ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
                           filename_table[0].name
                             ? filename_table[0].name
                             : "");
@@ -4478,8 +5438,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)
@@ -4553,20 +5512,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];
@@ -4602,10 +5569,13 @@ 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);
-  ASM_OUTPUT_DWARF_STRING (asm_out_file, string);
+  ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, string);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 }
 
@@ -4618,7 +5588,10 @@ dwarfout_start_new_source_file (filename)
 
   sprintf (label, SFNAMES_ENTRY_LABEL_FMT, lookup_filename (filename));
   sprintf (type_and_offset, "0x%08x+%s-%s",
-          ((unsigned) MACINFO_start << 24), label, SFNAMES_BEGIN_LABEL);
+          ((unsigned) MACINFO_start << 24),
+          /* Hack: skip leading '*' .  */
+          (*label == '*') + label,
+          (*SFNAMES_BEGIN_LABEL == '*') + SFNAMES_BEGIN_LABEL);
   generate_macinfo_entry (type_and_offset, "");
 }
 
@@ -4727,12 +5700,14 @@ dwarfout_init (asm_out_file, main_input_filename)
   ASM_OUTPUT_LABEL (asm_out_file, DATA_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .data1.  */
   /* Output a starting label for the .data1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, DATA1_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a starting label for the .rodata section.  */
 
@@ -4741,12 +5716,14 @@ dwarfout_init (asm_out_file, main_input_filename)
   ASM_OUTPUT_LABEL (asm_out_file, RODATA_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .rodata1.  */
   /* Output a starting label for the .rodata1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, RODATA1_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a starting label for the .bss section.  */
 
@@ -4757,26 +5734,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_NEWLINE (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
@@ -4797,21 +5784,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.  */
     
@@ -4883,7 +5873,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);
@@ -4904,12 +5894,14 @@ dwarfout_finish ()
   ASM_OUTPUT_LABEL (asm_out_file, DATA_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .data1.  */
   /* Output a terminator label for the .data1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, DATA1_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a terminator label for the .rodata section.  */
 
@@ -4918,12 +5910,14 @@ dwarfout_finish ()
   ASM_OUTPUT_LABEL (asm_out_file, RODATA_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .rodata1.  */
   /* Output a terminator label for the .rodata1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, RODATA1_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a terminator label for the .bss section.  */
 
@@ -4945,14 +5939,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)
        {
@@ -4963,7 +5960,7 @@ dwarfout_finish ()
          fputc ('\n', asm_out_file);
          ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
          ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
-         ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+         ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
          ASM_OUTPUT_POP_SECTION (asm_out_file);
        }
     
@@ -4972,7 +5969,7 @@ dwarfout_finish ()
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
       ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+      ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
       ASM_OUTPUT_POP_SECTION (asm_out_file);
     
       /* Generate the terminating entries for the .debug_aranges section.
@@ -4998,17 +5995,21 @@ dwarfout_finish ()
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA_END_LABEL, DATA_BEGIN_LABEL);
 
+#if 0 /* GNU C doesn't currently use .data1.  */
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA1_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA1_END_LABEL,
                                             DATA1_BEGIN_LABEL);
+#endif
 
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA_END_LABEL,
                                             RODATA_BEGIN_LABEL);
 
+#if 0 /* GNU C doesn't currently use .rodata1.  */
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA1_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA1_END_LABEL,
                                             RODATA1_BEGIN_LABEL);
+#endif
 
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, BSS_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, BSS_END_LABEL, BSS_BEGIN_LABEL);
@@ -5018,6 +6019,12 @@ dwarfout_finish ()
 
       ASM_OUTPUT_POP_SECTION (asm_out_file);
     }
+
+  /* There should not be any pending types left at the end.  We need
+     this now because it may not have been checked on the last call to
+     dwarfout_file_scope_decl.  */
+  if (pending_types != 0)
+    abort ();
 }
 
 #endif /* DWARF_DEBUGGING_INFO */