OSDN Git Service

x
authormerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 Dec 1996 22:31:23 +0000 (22:31 +0000)
committermerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 Dec 1996 22:31:23 +0000 (22:31 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@13258 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/Makefile.in
gcc/config/mips/mips.c
gcc/config/mips/t-iris6
gcc/dwarf2out.c
gcc/dwarfout.c
gcc/final.c
gcc/toplev.c
gcc/tree.c
gcc/varasm.c

index 7ef5cfb..ddb4ad5 100644 (file)
@@ -1078,14 +1078,14 @@ sublibobjc.a: cc1obj specs stmp-int-hdrs libgcc2.ready
 # linked using GCC on systems using COFF or ELF, for the sake of C++
 # constructors.
 $(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
-       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
-         $(MULTILIB_CFLAGS) -finhibit-size-directive -fno-inline-functions \
-         -g0 -c $(srcdir)/crtstuff.c -DCRT_BEGIN -o $(T)crtbegin$(objext)
+       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
+         -finhibit-size-directive -fno-inline-functions $(CRTSTUFF_T_CFLAGS) \
+         -c $(srcdir)/crtstuff.c -DCRT_BEGIN -o $(T)crtbegin$(objext)
 
 $(T)crtend.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
-       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
-         $(MULTILIB_CFLAGS) -finhibit-size-directive -fno-inline-functions \
-         -g0 -c $(srcdir)/crtstuff.c -DCRT_END -o $(T)crtend$(objext)
+       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
+         -finhibit-size-directive -fno-inline-functions $(CRTSTUFF_T_CFLAGS) \
+         -c $(srcdir)/crtstuff.c -DCRT_END -o $(T)crtend$(objext)
 
 # On some systems we also want to install versions of these files
 # compiled using PIC for use in shared libraries.
index 10545bb..c3a3b2d 100644 (file)
@@ -4940,7 +4940,7 @@ compute_frame_size (size)
                              + gp_reg_rounded + fp_reg_size
                              - fp_inc * UNITS_PER_FPREG);
       current_frame_info.fp_sp_offset = offset;
-      current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD;
+      current_frame_info.fp_save_offset = offset - total_size;
     }
   else
     {
@@ -5066,7 +5066,25 @@ save_restore_insns (store_p, large_reg, large_offset, file)
                                                  GEN_INT (gp_offset - base_offset)));
 
                  if (store_p)
-                   emit_move_insn (mem_rtx, reg_rtx);
+                   {
+                     rtx insn = emit_move_insn (mem_rtx, reg_rtx);
+
+                     if (write_symbols == DWARF2_DEBUG)
+                       {
+                         int offset = (gp_offset
+                                       - current_frame_info.total_size);
+                         if (regno == GP_REG_FIRST + 31)
+                           REG_NOTES (insn)
+                             = gen_rtx (EXPR_LIST, REG_RETURN_SAVE,
+                                        GEN_INT (offset), REG_NOTES (insn));
+                         else
+                           REG_NOTES (insn)
+                             = gen_rtx (EXPR_LIST, REG_SAVE,
+                                        gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
+                                                 GEN_INT (offset)),
+                                        REG_NOTES (insn));
+                       }
+                   }
                  else if (!TARGET_ABICALLS || mips_abi != ABI_32
                           || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
                    emit_move_insn (reg_rtx, mem_rtx);
@@ -5179,7 +5197,20 @@ save_restore_insns (store_p, large_reg, large_offset, file)
                                                  GEN_INT (fp_offset - base_offset)));
 
                  if (store_p)
-                   emit_move_insn (mem_rtx, reg_rtx);
+                   {
+                     rtx insn = emit_move_insn (mem_rtx, reg_rtx);
+
+                     if (write_symbols == DWARF2_DEBUG)
+                       {
+                         int offset = (gp_offset
+                                       - current_frame_info.total_size);
+                         REG_NOTES (insn)
+                           = gen_rtx (EXPR_LIST, REG_SAVE,
+                                      gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
+                                               GEN_INT (offset)),
+                                      REG_NOTES (insn));
+                       }
+                   }
                  else
                    emit_move_insn (reg_rtx, mem_rtx);
                }
@@ -5405,6 +5436,8 @@ mips_expand_prologue ()
       /* If we are doing svr4-abi, sp move is done by function_prologue.  */
       if (!TARGET_ABICALLS || mips_abi != ABI_32)
        {
+         rtx insn;
+
          if (tsize > 32767)
            {
              tmp_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
@@ -5413,21 +5446,37 @@ mips_expand_prologue ()
            }
 
          if (TARGET_LONG64)
-           emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                  tsize_rtx));
+           insn = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
+                                         tsize_rtx));
          else
-           emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                  tsize_rtx));
+           insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                                         tsize_rtx));
+
+         if (write_symbols == DWARF2_DEBUG)
+           REG_NOTES (insn)
+             = gen_rtx (EXPR_LIST, REG_FRAME,
+                        gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
+                                 GEN_INT (tsize)),
+                        REG_NOTES (insn));
        }
 
       save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0);
 
       if (frame_pointer_needed)
        {
+         rtx insn;
+
          if (TARGET_64BIT)
-           emit_insn (gen_movdi (frame_pointer_rtx, stack_pointer_rtx));
+           insn= emit_insn (gen_movdi (frame_pointer_rtx, stack_pointer_rtx));
          else
-           emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+           insn= emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+
+         if (write_symbols == DWARF2_DEBUG)
+           REG_NOTES (insn)
+             = gen_rtx (EXPR_LIST, REG_FRAME,
+                        gen_rtx (PLUS, VOIDmode, frame_pointer_rtx,
+                                 GEN_INT (tsize)),
+                        REG_NOTES (insn));
        }
 
       if (TARGET_ABICALLS && mips_abi != ABI_32)
index e831459..85a63f0 100644 (file)
@@ -17,3 +17,4 @@ INSTALL_LIBGCC = install-multilib
 # end labels to the .ctors and .dtors section when we link using gcc.
 
 EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
+CRTSTUFF_T_CFLAGS=-g1
index 6ac7d45..8902630 100644 (file)
@@ -198,8 +198,7 @@ typedef struct dw_fde_struct
   {
     unsigned long dw_fde_offset;
     char *dw_fde_begin;
-    char *dw_fde_end_prolog;
-    char *dw_fde_begin_epilogue;
+    char *dw_fde_current_label;
     char *dw_fde_end;
     dw_cfi_ref dw_fde_cfi;
   }
@@ -294,23 +293,12 @@ extern char *language_string;
 #define DWARF_ARANGES_HEADER_SIZE \
   (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
 
-/* Length of the target-dependent instructions in the
-   Common Information Entry (CIE).
-   ??? This should be computed when the frame info is genericized.  */
-#ifdef MIPS_DEBUGGING_INFO
-#define DWARF_CIE_INSN_SIZE (2*3)
-#endif
-
-#ifndef DWARF_CIE_INSN_SIZE
-#define DWARF_CIE_INSN_SIZE 0
-#endif
-
 /* Fixed size portion of the CIE (including the length field).  */
-#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5 + DWARF_CIE_INSN_SIZE)
+#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5)
 
-/* Fixed size of the Common Information Entry in the call frame
-   information (.debug_frame) section rounded up to a word boundary.  */
-#define DWARF_CIE_SIZE DWARF_ROUND (DWARF_CIE_HEADER_SIZE, PTR_SIZE)
+/* The un-padded size of the CIE.  Initialized in calc_fde_sizes, used
+   in output_call_frame_info.  */
+static unsigned cie_size;
 
 /* Offsets recorded in opcodes are a multiple of this alignment factor.  */
 #define DWARF_CIE_DATA_ALIGNMENT -4
@@ -355,6 +343,9 @@ static unsigned long next_fde_offset;
 /* Record the root of the DIE's built for the current compilation unit.  */
 dw_die_ref comp_unit_die;
 
+/* The number of DIEs with a NULL parent waiting to be relocated.  */
+static int limbo_die_count;
+
 /* Pointer to an array of filenames referenced by this compilation unit.  */
 static char **file_table;
 
@@ -381,21 +372,6 @@ static char *primary_filename;
    assigns numbers to the blocks in the same way.  */
 static unsigned next_block_number = 2;
 
-/* A pointer to the base of a list of references to DIE's that describe
-   types.  The table is indexed by TYPE_UID() which is a unique number,
-   indentifying each type.  */
-static dw_die_ref *type_die_table;
-
-/* Number of elements currently allocated for type_die_table.  */
-static unsigned type_die_table_allocated;
-
-/* Number of elements in type_die_table currently in use.  */
-static unsigned type_die_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
-   type_die_table.  */
-#define TYPE_DIE_TABLE_INCREMENT 4096
-
 /* A pointer to the base of a table of references to DIE's that describe
    declarations.  The table is indexed by DECL_UID() which is a unique
    number, indentifying each decl.  */
@@ -481,6 +457,9 @@ static unsigned fde_table_in_use;
    fde_table.  */
 #define FDE_TABLE_INCREMENT 256
 
+/* A list of call frame insns for the CIE.  */
+static dw_cfi_ref cie_cfi_head;
+
 /* A pointer to the base of a table that contains a list of publicly
    accessible names.  */
 static pubname_ref pubname_table;
@@ -509,6 +488,26 @@ static unsigned arange_table_in_use;
    arange_table.  */
 #define ARANGE_TABLE_INCREMENT 64
 
+/* A pointer to the base of a list of pending types which we haven't
+   generated DIEs for yet, but which we will have to come back to
+   later on.  */
+
+static tree *pending_types_list;
+
+/* Number of elements currently allocated for the pending_types_list.  */
+
+static unsigned pending_types_allocated;
+
+/* Number of elements of pending_types_list currently in use.  */
+
+static unsigned pending_types;
+
+/* Size (in elements) of increments by which we may expand the pending
+   types list.  Actually, a single hunk of space of this size should
+   be enough for most typical programs.         */
+
+#define PENDING_TYPES_INCREMENT 64
+
 /* The number of the current function definition for which debugging
    information is being generated.  These numbers range from 1 up to the
    maximum number of function definitions contained within the current
@@ -522,10 +521,6 @@ static unsigned current_funcdef_number = 1;
    associated with the current function (body) definition.  */
 static unsigned current_funcdef_fde;
 
-/* Record the size of the frame, so that the DW_AT_frame_base
-   attribute can be set properly in gen_subprogram_die.  */
-static long int current_funcdef_frame_size = 0;
-
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
 static int comp_unit_has_inlines;
@@ -544,6 +539,7 @@ static void gen_decl_die ();
 static unsigned lookup_filename ();
 static int constant_size PROTO((long unsigned));
 static enum dwarf_form value_format PROTO((dw_val_ref));
+static unsigned reg_number ();
 
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
@@ -823,9 +819,14 @@ char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 #endif
 
 /* The DWARF 2 CFA column which tracks the return address.  Normally this
-   is the first column after all of the hard registers.  */
+   is the column for PC, or the first column after all of the hard
+   registers.  */
 #ifndef DWARF_FRAME_RETURN_COLUMN
-#define DWARF_FRAME_RETURN_COLUMN      FIRST_PSEUDO_REGISTER
+#ifdef PC_REGNUM
+#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGNUM (PC_REGNUM)
+#else
+#define DWARF_FRAME_RETURN_COLUMN      FIRST_PSEUDO_REGISTER + 1
+#endif
 #endif
 
 /* The mapping from gcc register number to DWARF 2 CFA column number.  By
@@ -1851,13 +1852,12 @@ block_ultimate_origin (block)
    of a virtual function may refer to a base class, so we check the 'this'
    parameter.  */
 
-tree
+static tree
 decl_class_context (decl)
      tree decl;
 {
   tree context = NULL_TREE;
-  if (TREE_CODE (decl) != FUNCTION_DECL
-      || ! DECL_VIRTUAL_P (decl))
+  if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
     context = DECL_CONTEXT (decl);
   else
     context = TYPE_MAIN_VARIANT
@@ -2325,9 +2325,9 @@ new_die (tag_value, parent_die)
       die->die_attr = NULL;
       die->die_attr_last = NULL;
       if (parent_die != NULL)
-       {
-         add_child_die (parent_die, die);
-       }
+       add_child_die (parent_die, die);
+      else
+       ++limbo_die_count;
     }
   return die;
 }
@@ -2337,9 +2337,7 @@ inline dw_die_ref
 lookup_type_die (type)
      register tree type;
 {
-  register unsigned type_id = TYPE_UID (type);
-  return (type_id < type_die_table_in_use)
-    ? type_die_table[type_id] : NULL;
+  return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
 }
 
 /* Equate a DIE to a given type specifier.  */
@@ -2348,25 +2346,7 @@ equate_type_number_to_die (type, type_die)
      register tree type;
      register dw_die_ref type_die;
 {
-  register unsigned type_id = TYPE_UID (type);
-  register unsigned num_allocated;
-  if (type_id >= type_die_table_allocated)
-    {
-      num_allocated = (((type_id + 1)
-                       + TYPE_DIE_TABLE_INCREMENT - 1)
-                      / TYPE_DIE_TABLE_INCREMENT)
-       * TYPE_DIE_TABLE_INCREMENT;
-      type_die_table = (dw_die_ref *) xrealloc (type_die_table,
-                                      sizeof (dw_die_ref) * num_allocated);
-      bzero (&type_die_table[type_die_table_allocated],
-         (num_allocated - type_die_table_allocated) * sizeof (dw_die_ref));
-      type_die_table_allocated = num_allocated;
-    }
-  if (type_id >= type_die_table_in_use)
-    {
-      type_die_table_in_use = (type_id + 1);
-    }
-  type_die_table[type_id] = type_die;
+  TYPE_SYMTAB_POINTER (type) = (char *) type_die;
 }
 
 /* Return the DIE associated with a given declaration.  */
@@ -3657,6 +3637,212 @@ output_compilation_unit_header ()
   fputc ('\n', asm_out_file);
 }
 
+/* Extract the register and offset values from RTL.  If no register number
+   is specified, return -1 to indicate frame-relative addressing.  */
+static void
+decode_cfi_rtl (rtl, regp, offsetp)
+     register rtx rtl;
+     register unsigned long *regp;
+     register long *offsetp;
+{
+  switch (GET_CODE (rtl))
+    {
+    case REG:
+      *regp = reg_number (rtl);
+      *offsetp = 0;
+      break;
+    case PLUS:
+      *regp = reg_number (XEXP (rtl, 0));
+      *offsetp = INTVAL (XEXP (rtl, 1));
+      break;
+    case CONST_INT:
+      *regp = (unsigned long) -1;
+      *offsetp = INTVAL (rtl);
+      break;
+    default:
+      abort ();
+    }
+}
+
+/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
+   or to the CIE if LABEL is NULL.  */
+static void
+add_fde_cfi (label, cfi)
+     register char * label;
+     register dw_cfi_ref cfi;
+{
+  if (label)
+    {
+      register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
+      if (fde->dw_fde_current_label == NULL
+         || strcmp (label, fde->dw_fde_current_label) != 0)
+       {
+         register dw_cfi_ref xcfi;
+
+         fde->dw_fde_current_label = label = xstrdup (label);
+
+         /* Set the location counter to the new label.  */
+         xcfi = new_cfi ();
+         xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
+         xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
+         add_cfi (&fde->dw_fde_cfi, xcfi);
+       }
+      add_cfi (&fde->dw_fde_cfi, cfi);
+    }
+  else
+    add_cfi (&cie_cfi_head, cfi);
+}
+
+/* Subroutine of lookup_cfa.  */
+inline void
+lookup_cfa_1 (cfi, regp, offsetp)
+     register dw_cfi_ref cfi;
+     register unsigned long *regp;
+     register long *offsetp;
+{
+  switch (cfi->dw_cfi_opc)
+    {
+    case DW_CFA_def_cfa_offset:
+      *offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset;
+      break;
+    case DW_CFA_def_cfa_register:
+      *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+      break;
+    case DW_CFA_def_cfa:
+      *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+      *offsetp = cfi->dw_cfi_oprnd2.dw_cfi_offset;
+      break;
+    }
+}
+
+/* Find the previous value for the CFA.  */
+static void
+lookup_cfa (regp, offsetp)
+     register unsigned long *regp;
+     register long *offsetp;
+{
+  register dw_cfi_ref cfi;
+  *regp = (unsigned long) -1;
+  *offsetp = 0;
+
+  for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
+    lookup_cfa_1 (cfi, regp, offsetp);
+  if (fde_table_in_use)
+    {
+      register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
+      for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
+       lookup_cfa_1 (cfi, regp, offsetp);
+    }
+}
+
+/* Entry point to update the canonical frame address (CFA).
+   LABEL is passed to add_fde_cfi.  RTL is either:
+
+   a REG:  The frame is at 0(REG).
+   a PLUS of a REG and a CONST_INT:  The frame is at CONST(REG).  */
+void
+dwarf2out_def_cfa (label, rtl)
+     register char * label;
+     register rtx rtl;
+{
+  register dw_cfi_ref cfi;
+  unsigned long reg, old_reg;
+  long offset, old_offset;
+
+  decode_cfi_rtl (rtl, &reg, &offset);
+  lookup_cfa (&old_reg, &old_offset);
+
+  if (reg == old_reg && offset == old_offset)
+    return;
+
+  cfi = new_cfi ();
+
+  if (reg == old_reg)
+    {
+      cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
+      cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
+    }
+#ifndef MIPS_DEBUGGING_INFO  /* SGI dbx thinks this means no offset.  */
+  else if (offset == old_offset && old_reg != (unsigned long) -1)
+    {
+      cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
+      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+    }
+#endif
+  else
+    {
+      cfi->dw_cfi_opc = DW_CFA_def_cfa;
+      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+      cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
+    }
+
+  add_fde_cfi (label, cfi);
+}
+
+/* Add the CFI for saving a register.  REG is the CFA column number.
+   LABEL is passed to add_fde_cfi.
+   RTL is either:
+
+   a REG:  The register is saved in REG.
+   a CONST_INT:  The register is saved at an offset of CONST
+     from the CFA.  */
+static void
+reg_save (label, reg, rtl)
+     register char * label;
+     register unsigned long reg;
+     register rtx rtl;
+{
+  register dw_cfi_ref cfi;
+  unsigned long sreg;
+  long offset;
+
+  cfi = new_cfi ();
+
+  cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+
+  decode_cfi_rtl (rtl, &sreg, &offset);
+  offset /= DWARF_CIE_DATA_ALIGNMENT;
+
+  if (sreg == (unsigned long) -1)
+    {
+      if (reg & ~0x3f)
+       /* The register number won't fit in 6 bits, so we have to use
+          the long form.  */
+       cfi->dw_cfi_opc = DW_CFA_offset_extended;
+      else
+       cfi->dw_cfi_opc = DW_CFA_offset;
+      cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
+    }
+  else
+    {
+      cfi->dw_cfi_opc = DW_CFA_register;
+      cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
+    }
+
+  add_fde_cfi (label, cfi);
+}
+
+/* Entry point for saving a register.  REG is the GCC register number.
+   LABEL and RTL are passed to reg_save.  */
+void
+dwarf2out_reg_save (label, reg, rtl)
+     register char * label;
+     register unsigned long reg;
+     register rtx rtl;
+{
+  reg_save (label, DWARF_FRAME_REGNUM (reg), rtl);
+}
+
+/* Entry point for saving the return address.
+   LABEL and RTL are passed to reg_save.  */
+void
+dwarf2out_return_save (label, rtl)
+     register char * label;
+     register rtx rtl;
+{
+  reg_save (label, DWARF_FRAME_RETURN_COLUMN, rtl);
+}
+
 /* Return the size of a Call Frame Instruction.  */
 static unsigned long
 size_of_cfi (cfi)
@@ -3741,7 +3927,16 @@ calc_fde_sizes ()
   register unsigned long i;
   register dw_fde_ref fde;
   register unsigned long fde_size;
+  register dw_cfi_ref cfi;
   unsigned long fde_pad;
+
+  cie_size = DWARF_CIE_HEADER_SIZE;
+  for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
+    cie_size += size_of_cfi (cfi);
+
+  /* Initialize the beginning FDE offset.  */
+  next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+
   for (i = 0; i < fde_table_in_use; ++i)
     {
       fde = &fde_table[i];
@@ -3816,14 +4011,16 @@ output_cfi (cfi, fde)
        case DW_CFA_advance_loc2:
           ASM_OUTPUT_DWARF_DELTA2 (asm_out_file,
                                 cfi->dw_cfi_oprnd1.dw_cfi_addr,
-                                fde->dw_fde_begin);
+                                fde->dw_fde_current_label);
           fputc ('\n', asm_out_file);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
          break;
        case DW_CFA_advance_loc4:
           ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
                                 cfi->dw_cfi_oprnd1.dw_cfi_addr,
-                                fde->dw_fde_begin);
+                                fde->dw_fde_current_label);
           fputc ('\n', asm_out_file);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
          break;
 #ifdef MIPS_DEBUGGING_INFO
        case DW_CFA_MIPS_advance_loc8:
@@ -3873,12 +4070,14 @@ output_call_frame_info ()
   register unsigned long i, j;
   register dw_fde_ref fde;
   register unsigned long fde_size;
-  dw_cfi_node cfi_node;
   register dw_cfi_ref cfi;
   unsigned long fde_pad;
 
+  /* (re-)initialize the beginning FDE offset.  */
+  next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+
   /* Output the CIE. */
-  ASM_OUTPUT_DWARF_DATA (asm_out_file, DWARF_CIE_SIZE - DWARF_OFFSET_SIZE);
+  ASM_OUTPUT_DWARF_DATA (asm_out_file, next_fde_offset - DWARF_OFFSET_SIZE);
   if (flag_verbose_asm)
     {
       fprintf (asm_out_file, "\t%s Length of Common Information Entry",
@@ -3933,31 +4132,11 @@ output_call_frame_info ()
     }
   fputc ('\n', asm_out_file);
 
-  /* Output the CFA instructions common to all FDE's. */
-
-#ifdef MIPS_DEBUGGING_INFO
-
-  bzero (&cfi_node, sizeof (dw_cfi_node));
-  cfi = &cfi_node;
-
-  /* On entry, the Call Frame Address is in the stack pointer register.  */
-  cfi->dw_cfi_opc = DW_CFA_def_cfa;
-  cfi->dw_cfi_oprnd1.dw_cfi_reg_num
-    = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
-  cfi->dw_cfi_oprnd2.dw_cfi_offset = 0;
-  output_cfi (cfi);
-
-  /* Set the RA on entry to be the contents of r31.  */
-  cfi->dw_cfi_opc = DW_CFA_register;
-  cfi->dw_cfi_oprnd1.dw_cfi_reg_num = DWARF_FRAME_RETURN_COLUMN;
-  cfi->dw_cfi_oprnd2.dw_cfi_reg_num
-    = DWARF_FRAME_REGNUM (GP_REG_FIRST + 31);
-  output_cfi (cfi);
-
-#endif
+  for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
+    output_cfi (cfi);
 
   /* Pad the CIE out to an address sized boundary.  */
-  for (i = DWARF_CIE_HEADER_SIZE; i < DWARF_CIE_SIZE; ++i)
+  for (i = next_fde_offset - cie_size; i; --i)
     {
       /* Pad out to a pointer size boundary */
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
@@ -4006,10 +4185,9 @@ output_call_frame_info ()
 
       /* Loop through the Call Frame Instructions associated with
         this FDE.  */
+      fde->dw_fde_current_label = fde->dw_fde_begin;
       for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
-       {
-         output_cfi (cfi, fde);
-       }
+       output_cfi (cfi, fde);
 
       /* Pad to a double word boundary.  */
       for (j = 0; j < fde_pad; ++j)
@@ -4404,37 +4582,34 @@ output_line_info ()
            }
          fputc ('\n', asm_out_file);
        }
-      if (line_info->dw_line_num != current_line)
+      line_offset = line_info->dw_line_num - current_line;
+      line_delta = line_offset - DWARF_LINE_BASE;
+      current_line = line_info->dw_line_num;
+      if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
        {
-         line_offset = line_info->dw_line_num - current_line;
-         line_delta = line_offset - DWARF_LINE_BASE;
-         current_line = line_info->dw_line_num;
-         if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+                                 DWARF_LINE_OPCODE_BASE + line_delta);
+         if (flag_verbose_asm)
            {
-             ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
-                                     DWARF_LINE_OPCODE_BASE + line_delta);
-             if (flag_verbose_asm)
-               {
-                 fprintf (asm_out_file,
-                          "\t%s line %d", ASM_COMMENT_START, current_line);
-               }
-             fputc ('\n', asm_out_file);
+             fprintf (asm_out_file,
+                      "\t%s line %d", ASM_COMMENT_START, current_line);
            }
-         else
+         fputc ('\n', asm_out_file);
+       }
+      else
+       {
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
+         if (flag_verbose_asm)
            {
-             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
-             if (flag_verbose_asm)
-               {
-                 fprintf (asm_out_file,
-                          "\t%s advance to line %d",
-                          ASM_COMMENT_START, current_line);
-               }
-             fputc ('\n', asm_out_file);
-             output_sleb128 (line_offset);
-             fputc ('\n', asm_out_file);
-             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
-             fputc ('\n', asm_out_file);
+             fprintf (asm_out_file,
+                      "\t%s advance to line %d",
+                      ASM_COMMENT_START, current_line);
            }
+         fputc ('\n', asm_out_file);
+         output_sleb128 (line_offset);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+         fputc ('\n', asm_out_file);
        }
       strcpy (prev_line_label, line_label);
     }
@@ -4771,15 +4946,36 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
 
   if (code != ERROR_MARK)
     {
-      /* Take the MAIN_VARIANT here to avoid C typedef types. */
-      type = build_type_variant (TYPE_MAIN_VARIANT (type),
-                                is_const_type, is_volatile_type);
+      type = build_type_variant (type, is_const_type, is_volatile_type);
 
       mod_type_die = lookup_type_die (type);
       if (mod_type_die)
        return mod_type_die;
 
-      if (is_const_type)
+      /* Handle C typedef types. */
+      if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+         && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+       {
+         tree dtype = TREE_TYPE (TYPE_NAME (type));
+         if (type == dtype)
+           {
+             /* For a named type, use the typedef.  */
+             gen_type_die (type, context_die);
+             mod_type_die = lookup_type_die (type);
+           }
+         else if (is_const_type < TYPE_READONLY (dtype)
+                  || is_volatile_type < TYPE_VOLATILE (dtype))
+           /* cv-unqualified version of named type.  Just use the unnamed
+              type to which it refers.  */
+           mod_type_die = modified_type_die
+             (DECL_ORIGINAL_TYPE (TYPE_NAME (type)),
+              is_const_type, is_volatile_type);
+         /* else cv-qualified version of named type; fall through.  */
+       }
+
+      if (mod_type_die)
+       /* OK */;
+      else if (is_const_type)
        {
          mod_type_die = new_die (DW_TAG_const_type, comp_unit_die);
          sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
@@ -4828,13 +5024,9 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
             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' is
-            labeling a given type DIE for future reference, it always only
-            handles DIEs representing *main variants*, and it never even
-            knows about non-main-variants.).  */
+            ..._TYPE node.  */
          mod_type_die = lookup_type_die (type_main_variant (type));
-         if (mod_type_die == NULL)
-           abort ();
+         assert (mod_type_die != NULL);
        }
     }
   if (sub_die != NULL)
@@ -5841,11 +6033,15 @@ add_pure_or_virtual_attribute (die, func_decl)
      register dw_die_ref die;
      register tree func_decl;
 {
-  if (DECL_VIRTUAL_P (func_decl))
+  if (DECL_VINDEX (func_decl))
     {
       add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
       add_AT_loc (die, DW_AT_vtable_elem_location, new_loc_descr
                  (DW_OP_constu, TREE_INT_CST_LOW (DECL_VINDEX (func_decl))));
+      /* GNU extension: Record what type this method came from originally.  */
+      if (debug_info_level > DINFO_LEVEL_TERSE)
+       add_AT_die_ref (die, DW_AT_containing_type,
+                       lookup_type_die (DECL_CONTEXT (func_decl)));
     }
 }
 \f
@@ -5901,14 +6097,15 @@ scope_die_for (t, context_die)
 
   /* Function-local tags and functions get stuck in limbo until they are
      fixed up by decls_for_scope.  */
-  if (context_die == NULL)
+  if (context_die == NULL
+      && (TREE_CODE (t) == FUNCTION_DECL || is_tagged_type (t)))
     return NULL;
 
   /* Walk back up the declaration tree looking for a place to define
      this type.  */
   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
     containing_scope = TYPE_CONTEXT (t);
-  else if (TREE_CODE (t) == FUNCTION_DECL && DECL_VIRTUAL_P (t))
+  else if (TREE_CODE (t) == FUNCTION_DECL && DECL_VINDEX (t))
     containing_scope = decl_class_context (t);
   else
     containing_scope = DECL_CONTEXT (t);
@@ -5999,14 +6196,13 @@ type_tag (type)
       /* 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)
+      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+              && ! DECL_IGNORED_P (TYPE_NAME (type)))
        t = DECL_NAME (TYPE_NAME (type));
 
       /* Now get the name as a string, or invent one.  */
       if (t != 0)
-       {
-         name = IDENTIFIER_POINTER (t);
-       }
+       name = IDENTIFIER_POINTER (t);
     }
   return (name == 0 || *name == '\0') ? 0 : name;
 }
@@ -6145,6 +6341,43 @@ gen_entry_point_die (decl, context_die)
     }
 }
 
+/* Remember a type in the pending_types_list.  */
+
+static void
+pend_type (type)
+     register tree type;
+{
+  if (pending_types == pending_types_allocated)
+    {
+      pending_types_allocated += PENDING_TYPES_INCREMENT;
+      pending_types_list
+       = (tree *) xrealloc (pending_types_list,
+                            sizeof (tree) * pending_types_allocated);
+    }
+  pending_types_list[pending_types++] = type;
+}
+
+/* Output any pending types (from the pending_types list) which we can output
+   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.  */
+
+static void
+output_pending_types_for_scope (context_die)
+     register dw_die_ref context_die;
+{
+  register tree type;
+
+  while (pending_types)
+    {
+      --pending_types;
+      type = pending_types_list[pending_types];
+      gen_type_die (type, context_die);
+      assert (TREE_ASM_WRITTEN (type));
+    }
+}
+
 /* Generate a DIE to represent an inlined instance of an enumeration type.  */
 static void
 gen_inlined_enumeration_type_die (type, context_die)
@@ -6241,7 +6474,7 @@ gen_enumeration_type_die (type, context_die)
    it's the latter, then this function is only being called to output a
    DW_TAG_formal_parameter DIE to stand as a placeholder for some formal
    argument type of some subprogram type.  */
-static void
+static dw_die_ref
 gen_formal_parameter_die (node, context_die)
      register tree node;
      register dw_die_ref context_die;
@@ -6255,9 +6488,7 @@ gen_formal_parameter_die (node, context_die)
     case 'd':
       origin = decl_ultimate_origin (node);
       if (origin != NULL)
-       {
-         add_abstract_origin_attribute (parm_die, origin);
-       }
+       add_abstract_origin_attribute (parm_die, origin);
       else
        {
          add_name_and_src_coords_attributes (parm_die, node);
@@ -6269,13 +6500,9 @@ gen_formal_parameter_die (node, context_die)
            add_AT_flag (parm_die, DW_AT_artificial, 1);
        }
       if (DECL_ABSTRACT (node))
-       {
-         equate_decl_number_to_die (node, parm_die);
-       }
+       equate_decl_number_to_die (node, parm_die);
       else
-       {
-         add_location_or_const_value_attribute (parm_die, node);
-       }
+       add_location_or_const_value_attribute (parm_die, node);
       break;
 
       /* We were called with some kind of a ..._TYPE node.  */
@@ -6287,6 +6514,7 @@ gen_formal_parameter_die (node, context_die)
     default:
       abort ();
     }
+  return parm_die;
 }
 
 /* Generate a special type of DIE used as a stand-in for a trailing ellipsis
@@ -6334,12 +6562,17 @@ gen_formal_types_die (function_or_method_type, context_die)
      DW_TAG_formal_parameter DIE for each one.  */
   for (link = first_parm_type; link; link = TREE_CHAIN (link))
     {
+      register dw_die_ref parm_die;
+      
       formal_type = TREE_VALUE (link);
       if (formal_type == void_type_node)
        break;
 
       /* Output a (nameless) DIE to represent the formal parameter itself.  */
-      gen_formal_parameter_die (formal_type, context_die);
+      parm_die = gen_formal_parameter_die (formal_type, context_die);
+      if (TREE_CODE (function_or_method_type) == METHOD_TYPE
+         && link == first_parm_type)
+       add_AT_flag (parm_die, DW_AT_artificial, 1);
     }
 
   /* If this function type has an ellipsis, add a
@@ -6375,8 +6608,10 @@ gen_subprogram_die (decl, context_die)
   register unsigned fp_reg;
   register tree fn_arg_types;
   register tree outer_scope;
-  dw_die_ref old_die = lookup_decl_die (decl);
-  int declaration = (current_function_decl != decl);
+  register dw_die_ref old_die = lookup_decl_die (decl);
+  register int declaration = (current_function_decl != decl
+                             || context_die->die_tag == DW_TAG_structure_type
+                             || context_die->die_tag == DW_TAG_union_type);
 
   if (origin != NULL)
     {
@@ -6387,12 +6622,19 @@ gen_subprogram_die (decl, context_die)
     {
       register unsigned file_index
        = lookup_filename (DECL_SOURCE_FILE (decl));
-      if (get_AT_flag (old_die, DW_AT_declaration) != 1)
-       abort ();
+
+      assert (get_AT_flag (old_die, DW_AT_declaration) == 1);
 
       /* If the definition comes from the same place as the declaration,
-        use the old DIE.  */
-      if (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
+        maybe use the old DIE.  We always want the DIE for this function
+        that has the *_pc attributes to be under comp_unit_die so the
+        debugger can find it.  For inlines, that is the concrete instance,
+        so we can use the old DIE here.  For non-inline methods, we want a
+        specification DIE at toplevel, so we need a new DIE.  For local
+        class methods, this does not apply.  */
+      if ((DECL_ABSTRACT (decl) || old_die->die_parent == comp_unit_die
+          || context_die == NULL)
+         && get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
          && (get_AT_unsigned (old_die, DW_AT_decl_line)
              == DECL_SOURCE_LINE (decl)))
        {
@@ -6438,9 +6680,24 @@ gen_subprogram_die (decl, context_die)
       add_pure_or_virtual_attribute (subr_die, decl);
       if (DECL_ARTIFICIAL (decl))
        add_AT_flag (subr_die, DW_AT_artificial, 1);
+      if (TREE_PROTECTED (decl))
+       add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected);
+      else if (TREE_PRIVATE (decl))
+       add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private);
     }
 
-  if (DECL_ABSTRACT (decl))
+  if (declaration)
+    {
+      add_AT_flag (subr_die, DW_AT_declaration, 1);
+
+      /* The first time we see a member function, it is in the context of
+         the class to which it belongs.  We make sure of this by emitting
+         the class first.  The next time is the definition, which is
+         handled above.  The two may come from the same source text.  */
+      if (decl_class_context (decl))
+       equate_decl_number_to_die (decl, subr_die);
+    }
+  else if (DECL_ABSTRACT (decl))
     {
       if (DECL_DEFER_OUTPUT (decl))
        {
@@ -6460,17 +6717,6 @@ gen_subprogram_die (decl, context_die)
 
       equate_decl_number_to_die (decl, subr_die);
     }
-  else if (declaration)
-    {
-      add_AT_flag (subr_die, DW_AT_declaration, 1);
-
-      /* The first time we see a member function, it is in the context of
-         the class to which it belongs.  We make sure of this by emitting
-         the class first.  The next time is the definition, which is
-         handled above.  The two may come from the same source text.  */
-      if (decl_class_context (decl))
-       equate_decl_number_to_die (decl, subr_die);
-    }
   else if (!DECL_EXTERNAL (decl))
     {
       if (origin == NULL)
@@ -6503,16 +6749,6 @@ gen_subprogram_die (decl, context_die)
       if (current_function_needs_context)
        add_AT_loc (subr_die, DW_AT_static_link,
                    loc_descriptor (lookup_static_chain (decl)));
-
-#ifdef DWARF_GNU_EXTENSIONS
-      ASM_GENERATE_INTERNAL_LABEL (label_id, BODY_BEGIN_LABEL,
-                                  current_funcdef_number);
-      add_AT_lbl_id (subr_die, DW_AT_body_begin, label_id);
-      ASM_GENERATE_INTERNAL_LABEL (label_id, BODY_END_LABEL,
-                                  current_funcdef_number);
-      add_AT_lbl_id (subr_die, DW_AT_body_end, label_id);
-#endif
-
     }
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -6631,7 +6867,9 @@ gen_variable_die (decl, context_die)
   dw_die_ref old_die = lookup_decl_die (decl);
   int declaration
     = (DECL_EXTERNAL (decl)
-       || current_function_decl != decl_function_context (decl));
+       || current_function_decl != decl_function_context (decl)
+       || context_die->die_tag == DW_TAG_structure_type
+       || context_die->die_tag == DW_TAG_union_type);
 
   if (origin != NULL)
     {
@@ -6639,8 +6877,7 @@ gen_variable_die (decl, context_die)
     }
   else if (old_die)
     {
-      if (get_AT_flag (old_die, DW_AT_declaration) != 1)
-       abort ();
+      assert (get_AT_flag (old_die, DW_AT_declaration) == 1);
       add_AT_die_ref (var_die, DW_AT_specification, old_die);
       if (DECL_NAME (decl))
        {
@@ -6664,6 +6901,10 @@ gen_variable_die (decl, context_die)
        add_AT_flag (var_die, DW_AT_external, 1);
       if (DECL_ARTIFICIAL (decl))
        add_AT_flag (var_die, DW_AT_artificial, 1);
+      if (TREE_PROTECTED (decl))
+       add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected);
+      else if (TREE_PRIVATE (decl))
+       add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private);
     }
 
   if (declaration)
@@ -6792,9 +7033,14 @@ gen_field_die (decl, context_die)
       add_bit_size_attribute (decl_die, decl);
       add_bit_offset_attribute (decl_die, decl);
     }
-  add_data_member_location_attribute (decl_die, decl);
+  if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE)
+    add_data_member_location_attribute (decl_die, decl);
   if (DECL_ARTIFICIAL (decl))
     add_AT_flag (decl_die, DW_AT_artificial, 1);
+  if (TREE_PROTECTED (decl))
+    add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected);
+  else if (TREE_PRIVATE (decl))
+    add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private);
 }
 
 #if 0
@@ -6985,8 +7231,7 @@ gen_struct_or_union_type_die (type, context_die)
       && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
     nested = 1;
 
-  if (! type_die || nested)
-    scope_die = scope_die_for (type, context_die);
+  scope_die = scope_die_for (type, context_die);
 
   if (! type_die || (nested && scope_die == comp_unit_die))
     /* First occurrence of type or toplevel definition of nested class.  */
@@ -7003,13 +7248,16 @@ gen_struct_or_union_type_die (type, context_die)
   else
     remove_AT (type_die, DW_AT_declaration);
 
+  /* If we're not in the right context to be defining this type, defer to
+     avoid tricky recursion.  */
+  if (TYPE_SIZE (type) && decl_scope_depth > 0 && scope_die == comp_unit_die)
+    {
+      add_AT_flag (type_die, DW_AT_declaration, 1);
+      pend_type (type);
+    }
   /* If this type has been completed, then give it a byte_size attribute and
      then give a list of members.  */
-  if (TYPE_SIZE (type)
-      /* If we're getting a reference to one nested class from another
-        nested class, don't recurse.  */
-      && ! (nested && scope_die != context_die
-           && scope_die == lookup_type_die (TYPE_CONTEXT (type))))
+  else if (TYPE_SIZE (type))
     {
       /* Prevent infinite recursion in cases where the type of some member of 
          this type is expressed in terms of this type itself.  */
@@ -7018,6 +7266,14 @@ gen_struct_or_union_type_die (type, context_die)
       push_decl_scope (type);
       gen_member_die (type, type_die);
       pop_decl_scope ();
+      /* GNU extension: Record what type our vtable lives in.  */
+      if (TYPE_VFIELD (type))
+       {
+         tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type));
+         gen_type_die (vtype, context_die);
+         add_AT_die_ref (type_die, DW_AT_containing_type,
+                         lookup_type_die (vtype));
+       }
     }
   else
     add_AT_flag (type_die, DW_AT_declaration, 1);
@@ -7035,7 +7291,7 @@ gen_subroutine_type_die (type, context_die)
   equate_type_number_to_die (type, subr_die);
   add_prototyped_attribute (subr_die, type);
   add_type_attribute (subr_die, return_type, 0, 0, context_die);
-  gen_formal_types_die (type, context_die);
+  gen_formal_types_die (type, subr_die);
 }
 
 /* Generate a DIE for a type definition */
@@ -7044,25 +7300,33 @@ gen_typedef_die (decl, context_die)
      register tree decl;
      register dw_die_ref context_die;
 {
-  register tree origin = decl_ultimate_origin (decl);
   register dw_die_ref type_die;
+  register tree origin;
+
+  if (TREE_ASM_WRITTEN (decl))
+    return;
+  TREE_ASM_WRITTEN (decl) = 1;
+
   type_die = new_die (DW_TAG_typedef, scope_die_for (decl, context_die));
+  origin = decl_ultimate_origin (decl);
   if (origin != NULL)
-    {
-      add_abstract_origin_attribute (type_die, origin);
-    }
+    add_abstract_origin_attribute (type_die, origin);
   else
     {
+      register tree type;
       add_name_and_src_coords_attributes (type_die, decl);
-      add_type_attribute (type_die, TREE_TYPE (decl),
-                         TREE_READONLY (decl),
-                         TREE_THIS_VOLATILE (decl),
-                         context_die);
+      if (DECL_ORIGINAL_TYPE (decl))
+       {
+         type = DECL_ORIGINAL_TYPE (decl);
+         equate_type_number_to_die (TREE_TYPE (decl), type_die);
+       }
+      else
+       type = TREE_TYPE (decl);
+      add_type_attribute (type_die, type, TREE_READONLY (decl),
+                         TREE_THIS_VOLATILE (decl), context_die);
     }
   if (DECL_ABSTRACT (decl))
-    {
-      equate_decl_number_to_die (decl, type_die);
-    }
+    equate_decl_number_to_die (decl, type_die);
 }
 
 /* Generate a type description DIE.  */
@@ -7086,6 +7350,14 @@ gen_type_die (type, context_die)
       return;
     }
 
+  if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+      && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+    { 
+      TREE_ASM_WRITTEN (type) = 1;
+      gen_decl_die (TYPE_NAME (type), context_die);
+      return;
+    }
+
   switch (TREE_CODE (type))
     {
     case ERROR_MARK:
@@ -7152,12 +7424,27 @@ gen_type_die (type, context_die)
       if (TYPE_CONTEXT (type)
          && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
          && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
-       gen_type_die (TYPE_CONTEXT (type), context_die);
-      else if (TREE_CODE (type) == ENUMERAL_TYPE)
+       {
+         gen_type_die (TYPE_CONTEXT (type), context_die);
+
+         if (TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+           return;
+
+         /* If that failed, attach ourselves to the stub.  */
+         push_decl_scope (TYPE_CONTEXT (type));
+         context_die = lookup_type_die (TYPE_CONTEXT (type));
+       }
+
+      if (TREE_CODE (type) == ENUMERAL_TYPE)
        gen_enumeration_type_die (type, context_die);
       else
        gen_struct_or_union_type_die (type, context_die);
 
+      if (TYPE_CONTEXT (type)
+         && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+         && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+       pop_decl_scope ();
+
       /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix
         it up if it is ever completed.  gen_*_type_die will set it for us
         when appropriate.  */
@@ -7347,18 +7634,19 @@ decls_for_scope (stmt, context_die, depth)
   for (decl = BLOCK_VARS (stmt);
        decl != NULL; decl = TREE_CHAIN (decl))
     {
+      register dw_die_ref die;
+
       if (TREE_CODE (decl) == FUNCTION_DECL)
-       {
-         register dw_die_ref die = lookup_decl_die (decl);
-         add_child_die (context_die, die);
-       }
+       die = lookup_decl_die (decl);
       else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
+       die = lookup_type_die (TREE_TYPE (decl));
+      else
+       die = NULL;
+
+      if (die && die->die_parent == NULL)
        {
-         register dw_die_ref die = lookup_type_die (TREE_TYPE (decl));
-         if (die)
-           add_child_die (context_die, die);
-         else
-           gen_decl_die (decl, context_die);
+         add_child_die (context_die, die);
+         --limbo_die_count;
        }
       else
        gen_decl_die (decl, context_die);
@@ -7374,6 +7662,23 @@ decls_for_scope (stmt, context_die, depth)
     }
 }
 
+/* Is this a typedef we can avoid emitting?  */
+inline int
+is_redundant_typedef (decl)
+     register tree decl;
+{
+  if (TYPE_DECL_IS_STUB (decl))
+    return 1;
+  if (DECL_ARTIFICIAL (decl)
+      && DECL_CONTEXT (decl)
+      && is_tagged_type (DECL_CONTEXT (decl))
+      && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
+      && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
+    /* Also ignore the artificial member typedef for the class name.  */
+    return 1;
+  return 0;
+}
+
 /* Generate Dwarf debug information for a decl described by DECL.  */
 static void
 gen_decl_die (decl, context_die)
@@ -7417,10 +7722,21 @@ gen_decl_die (decl, context_die)
          break;
        }
 
-      /* Before we describe the FUNCTION_DECL itself, make sure that we have
-         described its return type.  */
       if (debug_info_level > DINFO_LEVEL_TERSE)
-       gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
+       {
+         /* Before we describe the FUNCTION_DECL itself, make sure that we
+            have described its return type.  */
+         gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
+
+         /* And its containing type.  */
+         origin = decl_class_context (decl);
+         if (origin)
+           gen_type_die (origin, context_die);
+
+         /* And its virtual context.  */
+         if (DECL_VINDEX (decl))
+           gen_type_die (DECL_CONTEXT (decl), context_die);
+       }
 
       /* Now output a DIE to represent the function itself.  */
       gen_subprogram_die (decl, context_die);
@@ -7444,9 +7760,10 @@ gen_decl_die (decl, context_die)
          gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die);
          break;
        }
-      gen_type_die (TREE_TYPE (decl), context_die);
 
-      if (! TYPE_DECL_IS_STUB (decl))
+      if (is_redundant_typedef (decl))
+       gen_type_die (TREE_TYPE (decl), context_die);
+      else
        {
          /* Output a DIE to represent the typedef itself.  */
          gen_typedef_die (decl, context_die);
@@ -7472,6 +7789,11 @@ gen_decl_die (decl, context_die)
          object.  */
       gen_type_die (TREE_TYPE (decl), context_die);
 
+      /* And its containing type.  */
+      origin = decl_class_context (decl);
+      if (origin)
+       gen_type_die (origin, context_die);
+
       /* 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
@@ -7488,8 +7810,9 @@ gen_decl_die (decl, context_die)
       break;
 
     case FIELD_DECL:
-      /* Ignore the nameless fields that are used to skip bits.  */
-      if (DECL_NAME (decl) != 0)
+      /* Ignore the nameless fields that are used to skip bits, but
+        handle C++ anonymous unions.  */
+      if (DECL_NAME (decl) != 0 || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
        {
          gen_type_die (member_declared_type (decl), context_die);
          gen_field_die (decl, context_die);
@@ -7610,7 +7933,15 @@ dwarf2out_decl (decl)
       /* Don't bother trying to generate any DIEs to represent any of the
          normal built-in types for the language we are compiling.  */
       if (DECL_SOURCE_LINE (decl) == 0)
-       return;
+       {
+         /* OK, we need to generate one for `bool' so GDB knows what type
+             comparisons have.  */
+         if ((get_AT_unsigned (comp_unit_die, DW_AT_language)
+              == DW_LANG_C_plus_plus)
+             && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE)
+           modified_type_die (TREE_TYPE (decl), 0, 0, NULL);
+         return;
+       }
 
       /* If we are in terse mode, don't generate any DIEs for types.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
@@ -7628,6 +7959,7 @@ dwarf2out_decl (decl)
     }
 
   gen_decl_die (decl, context_die);
+  output_pending_types_for_scope (comp_unit_die);
 
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_INITIAL (decl) != NULL)
@@ -7700,8 +8032,7 @@ dwarf2out_begin_prologue ()
   /* Add the new FDE at the end of the fde_table.  */
   fde = &fde_table[fde_table_in_use++];
   fde->dw_fde_begin = xstrdup (label);
-  fde->dw_fde_end_prolog = NULL;
-  fde->dw_fde_begin_epilogue = NULL;
+  fde->dw_fde_current_label = NULL;
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
 }
@@ -7712,100 +8043,51 @@ dwarf2out_begin_prologue ()
 void
 dwarf2out_begin_function ()
 {
+#ifdef MIPS_DEBUGGING_INFO
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
   register long int offset;
   register dw_fde_ref fde;
   register dw_cfi_ref cfi;
+  register int regno, fp_inc;
 
   function_section (current_function_decl);
   ASM_GENERATE_INTERNAL_LABEL (label, BODY_BEGIN_LABEL,
                               current_funcdef_number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 
-  /* Record the end-of-prolog location in the FDE.  */
-  fde = &fde_table[fde_table_in_use - 1];
-  fde->dw_fde_end_prolog = xstrdup (label);
-
-#ifdef MIPS_DEBUGGING_INFO
-
-  /* Set the location counter to the end of the function prolog.  */
-  cfi = new_cfi ();
-  cfi->dw_cfi_opc = DW_CFA_advance_loc4;
-  cfi->dw_cfi_oprnd1.dw_cfi_addr = xstrdup (label);
-  add_cfi (&fde->dw_fde_cfi, cfi);
-
   /* Define the CFA as an offset from either the frame pointer
      or the stack pointer.  */
-  cfi = new_cfi ();
-  cfi->dw_cfi_opc = DW_CFA_def_cfa;
-  cfi->dw_cfi_oprnd1.dw_cfi_reg_num
-    = DWARF_FRAME_REGNUM (frame_pointer_needed ? FRAME_POINTER_REGNUM
-                         : STACK_POINTER_REGNUM);
-  offset = current_frame_info.total_size;
-  cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
-  add_cfi (&fde->dw_fde_cfi, cfi);
-
-  /* record the frame size for later definition of the DW_AT_frame_base
-     attribute.  */
-  current_funcdef_frame_size = offset;
-
-  /* Define the rule for restoring the stack pointer.  */
-  if (frame_pointer_needed)
-    {
-      /* Restore the stack register from the frame pointer.  */
-      cfi = new_cfi ();
-      cfi->dw_cfi_opc = DW_CFA_register;
-      cfi->dw_cfi_oprnd1.dw_cfi_reg_num
-       = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
-      cfi->dw_cfi_oprnd2.dw_cfi_reg_num
-       = DWARF_FRAME_REGNUM (FRAME_POINTER_REGNUM);
-      add_cfi (&fde->dw_fde_cfi, cfi);
-    }
-
-  /* If RA is saved on the stack, define it here.  */
-  if (regs_ever_live[31])
-    {
-      offset = current_frame_info.gp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
-      assert (offset >= 0);
-      cfi = new_cfi ();
-      cfi->dw_cfi_opc = DW_CFA_offset_extended;
-      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = DWARF_FRAME_RETURN_COLUMN;
-      cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
-      add_cfi (&fde->dw_fde_cfi, cfi);
-    }
+  dwarf2out_def_cfa
+    (label, gen_rtx (PLUS, VOIDmode,
+                    gen_rtx (REG, VOIDmode,
+                             (frame_pointer_needed ? FRAME_POINTER_REGNUM
+                              : STACK_POINTER_REGNUM)),
+                    GEN_INT (current_frame_info.total_size)));
+
+  /* Record the locations of the return address and any callee-saved regs.  */
+  offset = current_frame_info.gp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
+  for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; --regno)
+    if (current_frame_info.mask & (1<<regno))
+      {
+       assert (offset >= 0);
 
-  /* If FP is saved on the stack, define it here.  */
-  if (current_frame_info.mask & (1 << 30))
-    {
-      offset = (current_frame_info.gp_save_offset
-                - (((current_frame_info.mask >> 31) & 1) * UNITS_PER_WORD))
-               / DWARF_CIE_DATA_ALIGNMENT;
-      assert (offset >= 0);
-      cfi = new_cfi ();
-      cfi->dw_cfi_opc = DW_CFA_offset;
-      cfi->dw_cfi_oprnd1.dw_cfi_reg_num
-       = DWARF_FRAME_REGNUM (FRAME_POINTER_REGNUM);
-      cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
-      add_cfi (&fde->dw_fde_cfi, cfi);
-    }
+       if (regno == 31)
+         dwarf2out_return_save (label, GEN_INT (offset));
+       else
+         dwarf2out_reg_save (label, regno, GEN_INT (offset));
+       offset -= UNITS_PER_WORD / DWARF_CIE_DATA_ALIGNMENT;
+      }
 
+  fp_inc = (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) ? 1 : 2;
+  offset = current_frame_info.fp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
+  for (regno = FP_REG_LAST - 1; regno >= FP_REG_FIRST; regno -= fp_inc)
+    if (current_frame_info.fmask & (1 << (regno - FP_REG_FIRST)))
+      {
+       assert (offset >= 0);
+       dwarf2out_reg_save (label, regno, GEN_INT (offset));
+       offset -= (fp_inc * UNITS_PER_FPREG) / DWARF_CIE_DATA_ALIGNMENT;
+      }
 #endif
-
-}
-
-/* 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
-dwarf2out_end_function ()
-{
-  dw_fde_ref fde;
-  char label[MAX_ARTIFICIAL_LABEL_BYTES];
-  function_section (current_function_decl);
-  ASM_GENERATE_INTERNAL_LABEL (label, BODY_END_LABEL, current_funcdef_number);
-  ASM_OUTPUT_LABEL (asm_out_file, label);
-  /* Record the ending code location in the FDE.  */
-  fde = &fde_table[fde_table_in_use - 1];
-  fde->dw_fde_begin_epilogue = xstrdup(label);
 }
 
 /* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -7998,13 +8280,6 @@ dwarf2out_init (asm_out_file, main_input_filename)
   /* skip the first entry - file numbers begin at 1 */
   file_table_in_use = 1;
 
-  /* Allocate the initial hunk of the type_die_table.  */
-  type_die_table
-    = (dw_die_ref *) xmalloc (TYPE_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
-  bzero (type_die_table, TYPE_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
-  type_die_table_allocated = TYPE_DIE_TABLE_INCREMENT;
-  type_die_table_in_use = 0;
-
   /* Allocate the initial hunk of the decl_die_table.  */
   decl_die_table
     = (dw_die_ref *) xmalloc (DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
@@ -8052,6 +8327,16 @@ dwarf2out_init (asm_out_file, main_input_filename)
   gen_compile_unit_die (main_input_filename);
 
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
+
+  /* Generate the CFA instructions common to all FDE's.  Do it now for the
+     sake of lookup_cfa.  */
+#ifdef MIPS_DEBUGGING_INFO
+  /* On entry, the Call Frame Address is in the stack pointer register.  */
+  dwarf2out_def_cfa (NULL, gen_rtx (REG, VOIDmode, STACK_POINTER_REGNUM));
+
+  /* Set the RA on entry to be the contents of r31.  */
+  dwarf2out_return_save (NULL, gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31));
+#endif
 }
 
 /* Output stuff that dwarf requires at the end of every file,
@@ -8107,8 +8392,7 @@ dwarf2out_finish ()
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
   calc_die_sizes (comp_unit_die);
 
-  /* Initialize the beginning FDE offset - and calculate sizes/offsets.  */
-  next_fde_offset = DWARF_CIE_SIZE;
+  /* calculate sizes/offsets for FDEs.  */
   calc_fde_sizes ();
 
   /* Output debugging information.  */
@@ -8127,15 +8411,20 @@ dwarf2out_finish ()
 
   if (fde_table_in_use)
     {
+#ifdef MIPS_DEBUGGING_INFO /* Not currently useful otherwise.  */
       /* Output call frame information.  */
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
       output_call_frame_info ();
+#endif
 
       /* Output the address range information.  */
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);
       output_aranges ();
     }
+
+  /* The only DIE we should have with a parent of NULL is comp_unit_die.  */
+  assert (limbo_die_count == 1);
 }
 #endif /* DWARF2_DEBUGGING_INFO */
index daddd0e..1d29394 100644 (file)
@@ -97,6 +97,21 @@ extern char *rindex ();
 
 #define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
 
+/* Define a macro which returns non-zero for a TYPE_DECL which was
+   implicitly generated for a tagged type.
+
+   Note that unlike the gcc front end (which generates a NULL named
+   TYPE_DECL node for each complete tagged type, each array type, and
+   each function type node created) the g++ front end generates a
+   _named_ TYPE_DECL node for each tagged type node created.
+   These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
+   generate a DW_TAG_typedef DIE for them.  */
+#define TYPE_DECL_IS_STUB(decl)                                \
+  (DECL_NAME (decl) == NULL                            \
+   || (DECL_ARTIFICIAL (decl)                          \
+       && is_tagged_type (TREE_TYPE (decl))            \
+       && decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
+
 extern int flag_traditional;
 extern char *version_string;
 extern char *language_string;
@@ -284,6 +299,12 @@ static unsigned current_funcdef_number = 1;
 
 static tree dwarf_last_decl;
 
+/* A flag indicating that we are emitting the member declarations of a
+   class, so member functions and variables should not be entirely emitted.
+   This is a kludge to avoid passing a second argument to output_*_die.  */
+
+static int in_class;
+
 /* Forward declarations for functions defined in this file.  */
 
 static char *dwarf_tag_name            PROTO((unsigned));
@@ -1169,6 +1190,27 @@ block_ultimate_origin (block)
     }
 }
 
+/* Get the class to which DECL belongs, if any.  In g++, the DECL_CONTEXT
+   of a virtual function may refer to a base class, so we check the 'this'
+   parameter.  */
+
+static tree
+decl_class_context (decl)
+     tree decl;
+{
+  tree context = NULL_TREE;
+  if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
+    context = DECL_CONTEXT (decl);
+  else
+    context = TYPE_MAIN_VARIANT
+      (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
+
+  if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
+    context = NULL_TREE;
+
+  return context;
+}
+
 static void
 output_unsigned_leb128 (value)
      register unsigned long value;
@@ -3007,8 +3049,8 @@ type_tag (type)
       /* 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)
+      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+              && ! DECL_IGNORED_P (TYPE_NAME (type)))
          t = DECL_NAME (TYPE_NAME (type));
 
       /* Now get the name as a string, or invent one.  */
@@ -3302,17 +3344,21 @@ output_global_subroutine_die (arg)
     equate_decl_number_to_die_number (decl);
   else
     {
-      if (! DECL_EXTERNAL (decl))
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && decl == current_function_decl)
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
          low_pc_attribute (function_start_label (decl));
          sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
          high_pc_attribute (label);
-         sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
-         body_begin_attribute (label);
-         sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
-         body_end_attribute (label);
+         if (use_gnu_debug_info_extensions)
+           {
+             sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+             body_begin_attribute (label);
+             sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+             body_end_attribute (label);
+           }
        }
     }
 }
@@ -3342,7 +3388,8 @@ output_global_variable_die (arg)
     equate_decl_number_to_die_number (decl);
   else
     {
-      if (!DECL_EXTERNAL (decl))
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && current_function_decl == decl_function_context (decl))
        location_or_const_value_attribute (decl);
     }
 }
@@ -3566,7 +3613,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);
@@ -3681,10 +3728,13 @@ output_local_subroutine_die (arg)
          low_pc_attribute (function_start_label (decl));
          sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
          high_pc_attribute (label);
-         sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
-         body_begin_attribute (label);
-         sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
-         body_end_attribute (label);
+         if (use_gnu_debug_info_extensions)
+           {
+             sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+             body_begin_attribute (label);
+             sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+             body_end_attribute (label);
+           }
        }
     }
 }
@@ -3990,7 +4040,9 @@ type_ok_for_scope (type, scope)
      (for C and C++ anyway) will be array types and function types.  */
 
   return is_tagged_type (type)
-        ? (TYPE_CONTEXT (type) == scope)
+        ? (TYPE_CONTEXT (type) == scope
+           || (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
+               && TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
         : (scope == NULL_TREE || ! is_tagged_type (scope));
 }
 
@@ -4058,6 +4110,17 @@ output_type (type, containing_scope)
   if (TREE_ASM_WRITTEN (type))
     return;
 
+  /* If this is a nested type whose containing class hasn't been
+     written out yet, writing it out will cover this one, too.  */
+
+  if (TYPE_CONTEXT (type)
+      && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+      && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+    {
+      output_type (TYPE_CONTEXT (type), containing_scope);
+      return;
+    }
+
   /* Don't generate any DIEs for this type now unless it is OK to do so
      (based upon what `type_ok_for_scope' tells us).  */
 
@@ -4168,13 +4231,9 @@ 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.
-
-          This loses for C++ nested types that are defined after their
-          containing class, but I don't see a good way to fix it.  I doubt
-          many people will be using DWARF 1 for C++ in any case.  */
+          scope tagged types.  */
 
-       if (TYPE_SIZE (type) == 0 && TYPE_CONTEXT (type) == NULL && !finalizing)
+       if (TYPE_SIZE (type) == 0 && !finalizing)
          return;       /* EARLY EXIT!  Avoid setting TREE_ASM_WRITTEN.  */
 
        /* Prevent infinite recursion in cases where the type of some
@@ -4233,6 +4292,8 @@ output_type (type, containing_scope)
                  output_die (output_inheritance_die, TREE_VEC_ELT (bases, i));
              }
 
+           ++in_class;
+
            {
              register tree normal_member;
 
@@ -4255,6 +4316,8 @@ output_type (type, containing_scope)
                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.  */
@@ -4458,6 +4521,24 @@ output_decls_for_scope (stmt, depth)
   }
 }
 
+/* Is this a typedef we can avoid emitting?  */
+
+inline int
+is_redundant_typedef (decl)
+     register tree decl;
+{
+  if (TYPE_DECL_IS_STUB (decl))
+    return 1;
+  if (DECL_ARTIFICIAL (decl)
+      && DECL_CONTEXT (decl)
+      && is_tagged_type (DECL_CONTEXT (decl))
+      && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
+      && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
+    /* Also ignore the artificial member typedef for the class name.  */
+    return 1;
+  return 0;
+}
+
 /* Output Dwarf .debug information for a decl described by DECL.  */
 
 static void
@@ -4518,6 +4599,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
@@ -4554,7 +4642,7 @@ output_decl (decl, containing_scope)
         we need to do here (and all we *can* do here) is to describe
         the *types* of its formal parameters.  */
 
-      if (DECL_INITIAL (decl) == NULL_TREE)
+      if (decl != current_function_decl || in_class)
        output_formal_types (TREE_TYPE (decl));
       else
        {
@@ -4644,45 +4732,45 @@ output_decl (decl, containing_scope)
                 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).  */
+         /* 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);
-
-       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);
+           register tree outer_scope = DECL_INITIAL (decl);
+
+           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);
+             }
          }
-      }
+       }
 
       /* Generate a terminator for the list of stuff `owned' by this
         function.  */
@@ -4699,19 +4787,19 @@ output_decl (decl, containing_scope)
         a return type or a formal parameter type of some function.  */
 
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-       if (DECL_NAME (decl) != NULL
-           || ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
+       if (! TYPE_DECL_IS_STUB (decl)
+           || (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
           return;
 
-      /* In the special case of a null-named TYPE_DECL node (representing
-        the declaration of some type tag), if the given TYPE_DECL is
+      /* In the special case of a TYPE_DECL node representing
+        the declaration of some type tag, if the given TYPE_DECL is
         marked as having been instantiated from some other (original)
         TYPE_DECL node (e.g. one which was generated within the original
         definition of an inline function) we have to generate a special
         (abbreviated) TAG_structure_type, TAG_union_type, or
         TAG_enumeration-type DIE here.  */
 
-      if (! DECL_NAME (decl) && DECL_ABSTRACT_ORIGIN (decl))
+      if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
        {
          output_tagged_type_instantiation (TREE_TYPE (decl));
          return;
@@ -4719,13 +4807,7 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (decl), containing_scope);
 
-      /* Note that unlike the gcc front end (which generates a NULL named
-        TYPE_DECL node for each complete tagged type, each array type,
-        and each function type node created) the g++ front end generates
-        a *named* TYPE_DECL node for each tagged type node created.
-        These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
-        generate a DW_TAG_typedef DIE for them.  */
-      if (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
+      if (! is_redundant_typedef (decl))
        /* Output a DIE to represent the typedef itself.  */
        output_die (output_typedef_die, decl);
       break;
@@ -4755,6 +4837,13 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (decl), containing_scope);
 
+      {
+       /* And its containing type.  */
+       register tree origin = decl_class_context (decl);
+       if (origin)
+         output_type (origin, containing_scope);
+      }
+
       /* If the following DIE will represent a data object definition for a
         data object with "extern" linkage, output a special "pubnames" DIE
         label just ahead of the actual DIE.  A reference to this label
@@ -5076,6 +5165,8 @@ 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);
@@ -5089,6 +5180,8 @@ 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);
@@ -5263,7 +5356,7 @@ dwarfout_line (filename, line)
       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;
 
       function_section (current_function_decl);
       sprintf (label, LINE_CODE_LABEL_FMT, ++last_line_entry_num);
@@ -5272,6 +5365,11 @@ dwarfout_line (filename, line)
       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;
+
       if (this_file_entry_num != prev_file_entry_num)
         {
           char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -5307,6 +5405,9 @@ generate_macinfo_entry (type_and_offset, string)
      register char *type_and_offset;
      register char *string;
 {
+  if (! use_gnu_debug_info_extensions)
+    return;
+
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
   fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
@@ -5466,32 +5567,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;
-       register unsigned len;
-       register char *dirname;
-
-       pwd = getpwd ();
-       if (!pwd)
-         pfatal_with_name ("getpwd");
-       len = strlen (pwd);
-       dirname = (char *) xmalloc (len + 2);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
+         ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
+         {
+           register char *pwd;
+           register unsigned len;
+           register char *dirname;
+
+           pwd = getpwd ();
+           if (!pwd)
+             pfatal_with_name ("getpwd");
+           len = strlen (pwd);
+           dirname = (char *) xmalloc (len + 2);
     
-       strcpy (dirname, pwd);
-       strcpy (dirname + len, "/");
-        ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
-        free (dirname);
-      }
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+           strcpy (dirname, pwd);
+           strcpy (dirname + len, "/");
+           ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+           free (dirname);
+         }
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
     
-      if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+      if (debug_info_level >= DINFO_LEVEL_VERBOSE
+         && use_gnu_debug_info_extensions)
        {
           /* Output a starting label for the .debug_macinfo section.  This
             label will be referenced by the AT_mac_info attribute in the
@@ -5512,21 +5617,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.  */
     
@@ -5664,14 +5772,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)
        {
index c38aada..40a0911 100644 (file)
@@ -1066,11 +1066,6 @@ final_end_function (first, file, optimize)
     dwarfout_end_function ();
 #endif
 
-#ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG)
-    dwarf2out_end_function ();
-#endif
-
 #ifdef XCOFF_DEBUGGING_INFO
   if (write_symbols == XCOFF_DEBUG)
     xcoffout_end_function (file, high_function_linenum);
index 61528b0..a10f4d9 100644 (file)
@@ -2776,15 +2776,6 @@ rest_of_type_compilation (type, toplev)
   if (write_symbols == SDB_DEBUG)
     TIMEVAR (symout_time, sdbout_symbol (TYPE_STUB_DECL (type), !toplev));
 #endif
-#ifdef DWARF_DEBUGGING_INFO
-  /* Don't write out function-scope types here.  */
-  if (write_symbols == DWARF_DEBUG && toplev)
-    TIMEVAR (symout_time, dwarfout_file_scope_decl (TYPE_STUB_DECL (type), 0));
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG)
-    TIMEVAR (symout_time, dwarf2out_decl (TYPE_STUB_DECL (type)));
-#endif
 }
 
 /* This is called from finish_function (within yyparse)
@@ -3904,19 +3895,11 @@ main (argc, argv, envp)
                { "gstabs+", DBX_DEBUG, 1 },
 #endif
 #ifdef DWARF_DEBUGGING_INFO
-               { "gdwarf-1", DWARF_DEBUG, 0 },
-               { "gdwarf-1+", DWARF_DEBUG, 1 },
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-               { "gdwarf-2", DWARF2_DEBUG, 0 },
-#endif
-#if defined (DWARF_DEBUGGING_INFO) || defined (DWARF2_DEBUGGING_INFO)
-#if PREFERRED_DEBUGGING_TYPE == DWARF_DEBUG || !defined (DWARF2_DEBUGGING_INFO)
                { "gdwarf", DWARF_DEBUG, 0 },
                { "gdwarf+", DWARF_DEBUG, 1 },
-#else
-               { "gdwarf", DWARF2_DEBUG, 0 },
 #endif
+#ifdef DWARF2_DEBUGGING_INFO
+               { "gdwarf-2", DWARF2_DEBUG, 0 },
 #endif
 #ifdef XCOFF_DEBUGGING_INFO
                { "gxcoff", XCOFF_DEBUG, 0 },
@@ -4398,3 +4381,58 @@ debug_undef (lineno, buffer)
     dwarf2out_undef (lineno, buffer);
 #endif /* DWARF2_DEBUGGING_INFO */
 }
+
+/* Record the relative location of the current stack frame at the PC value
+   indicated by LABEL if specified, or at the beginning of the function
+   if LABEL is NULL.  RTL is either:
+
+   a REG:  The frame is at 0(REG).
+   a PLUS of a REG and a CONST_INT:  The frame is at CONST(REG).  */
+
+void
+debug_frame (label, rtl)
+     char *label;
+     rtx rtl;
+{
+#ifdef DWARF2_DEBUGGING_INFO
+  if (write_symbols == DWARF2_DEBUG)
+    dwarf2out_def_cfa (label, rtl);
+#endif
+}
+
+/* Record that REGNO, a callee-saved register, has been saved somewhere.
+   LABEL is as for debug_frame.  RTL is either:
+
+   a REG:  The register is saved in REG.
+   a CONST_INT:  The register is saved at an offset of CONST
+     from the frame.  */
+
+void
+debug_reg_save (label, regno, rtl)
+     char *label;
+     unsigned regno;
+     rtx rtl;
+{
+#ifdef DWARF2_DEBUGGING_INFO
+  if (write_symbols == DWARF2_DEBUG)
+    dwarf2out_reg_save (label, regno, rtl);
+#endif
+}
+
+/* Record the location of the return address for the current frame.
+   LABEL is as for debug_frame.  RTL is either:
+
+   a REG:  The return address is saved in REG.
+   a CONST_INT:  The return address is saved at an offset of CONST
+     from the frame.  */
+
+void
+debug_return_save (label, rtl)
+     char *label;
+     rtx rtl;
+{
+#ifdef DWARF2_DEBUGGING_INFO
+  if (write_symbols == DWARF2_DEBUG)
+    dwarf2out_return_save (label, rtl);
+#endif
+}
index 6a1e953..fde0e9d 100644 (file)
@@ -1268,6 +1268,45 @@ get_identifier (text)
   return idp;                  /* <-- return if created */
 }
 
+/* If an identifier with the name TEXT (a null-terminated string) has
+   previously been referred to, return that node; otherwise return
+   NULL_TREE.  */
+
+tree
+maybe_get_identifier (text)
+     register char *text;
+{
+  register int hi;
+  register int i;
+  register tree idp;
+  register int len, hash_len;
+
+  /* Compute length of text in len.  */
+  for (len = 0; text[len]; len++);
+
+  /* Decide how much of that length to hash on */
+  hash_len = len;
+  if (warn_id_clash && len > id_clash_len)
+    hash_len = id_clash_len;
+
+  /* Compute hash code */
+  hi = hash_len * 613 + (unsigned) text[0];
+  for (i = 1; i < hash_len; i += 2)
+    hi = ((hi * 613) + (unsigned) (text[i]));
+
+  hi &= (1 << HASHBITS) - 1;
+  hi %= MAX_HASH_TABLE;
+  
+  /* Search table for identifier */
+  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
+    if (IDENTIFIER_LENGTH (idp) == len
+       && IDENTIFIER_POINTER (idp)[0] == text[0]
+       && !bcmp (IDENTIFIER_POINTER (idp), text, len))
+      return idp;              /* <-- return if found */
+
+  return NULL_TREE;
+}
+
 /* Enable warnings on similar identifiers (if requested).
    Done after the built-in identifiers are created.  */
 
index 9490238..a8c15df 100644 (file)
@@ -1175,25 +1175,15 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
              && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
            sdbout_symbol (decl, 0);
 #endif
-#ifdef DWARF_DEBUGGING_INFO
-         if (write_symbols == DWARF_DEBUG && top_level
-             && DECL_CONTEXT (decl))
-           dwarfout_file_scope_decl (decl, 0);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-         if (write_symbols == DWARF2_DEBUG && top_level
-             && DECL_CONTEXT (decl))
-           dwarf2out_decl (decl);
-#endif
        }
 
-      /* Only output DWARF debugging information for record-scope variables
-        here.  In the case of function-scope variables, the information
-        for them is output when we do our recursive traversal of the tree
-        representation for the entire containing function.  In the case of
-        file-scope variables, we output information for all of them at the
-        very end of compilation while we are doing our final traversal of
-        the chain of file-scope declarations.  */
+      /* Don't output any DWARF debugging information for variables here.
+        In the case of local variables, the information for them is output
+        when we do our recursive traversal of the tree representation for
+        the entire containing function.  In the case of file-scope variables,
+        we output information for all of them at the very end of compilation
+        while we are doing our final traversal of the chain of file-scope
+        declarations.  */
 
       return;
     }
@@ -1308,24 +1298,14 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
          && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
        sdbout_symbol (decl, 0);
 #endif
-#ifdef DWARF_DEBUGGING_INFO
-      if (write_symbols == DWARF_DEBUG && top_level
-         && DECL_CONTEXT (decl))
-       dwarfout_file_scope_decl (decl, 0);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-      if (write_symbols == DWARF2_DEBUG && top_level
-         && DECL_CONTEXT (decl))
-       dwarf2out_decl (decl);
-#endif
 
-      /* Only output DWARF debugging information for record-scope variables
-        here.  In the case of function-scope variables, the information
-        for them is output when we do our recursive traversal of the tree
-        representation for the entire containing function.  In the case of
-        file-scope variables, we output information for all of them at the
-        very end of compilation while we are doing our final traversal of
-        the chain of file-scope declarations.  */
+      /* Don't output any DWARF debugging information for variables here.
+        In the case of local variables, the information for them is output
+        when we do our recursive traversal of the tree representation for
+        the entire containing function.  In the case of file-scope variables,
+        we output information for all of them at the very end of compilation
+        while we are doing our final traversal of the chain of file-scope
+        declarations.  */
 
 #if 0 /* ??? We should either delete this or add a comment describing what
         it was intended to do and why we shouldn't delete it.  */
@@ -1729,15 +1709,13 @@ assemble_name (file, name)
      char *name;
 {
   char *real_name;
-  int save_warn_id_clash = warn_id_clash;
+  tree id;
 
   STRIP_NAME_ENCODING (real_name, name);
 
-  /* Don't warn about an identifier name length clash on this name, since
-     it can be a user symbol suffixed by a number.  */
-  warn_id_clash = 0;
-  TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
-  warn_id_clash = save_warn_id_clash;
+  id = maybe_get_identifier (real_name);
+  if (id)
+    TREE_SYMBOL_REFERENCED (id) = 1;
 
   if (name[0] == '*')
     {