OSDN Git Service

* configure.in (all_headers, all_lib2funcs): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 6f8d335..2cbe716 100644 (file)
@@ -5,25 +5,24 @@
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
-/* TODO: Implement .debug_str handling, and share entries somehow.
-        Emit .debug_line header even when there are no functions, since
+/* TODO: Emit .debug_line header even when there are no functions, since
           the file numbers are used by .debug_info.  Alternately, leave
           out locations for types and decls.
         Avoid talking about ctors and op= for PODs.
@@ -47,6 +46,7 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "output.h"
 #include "expr.h"
+#include "libfuncs.h"
 #include "except.h"
 #include "dwarf2.h"
 #include "dwarf2out.h"
@@ -56,6 +56,15 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "md5.h"
 #include "tm_p.h"
+#include "diagnostic.h"
+#include "debug.h"
+#include "target.h"
+#include "langhooks.h"
+#include "hashtable.h"
+
+#ifdef DWARF2_DEBUGGING_INFO
+static void dwarf2out_source_line      PARAMS ((unsigned int, const char *));
+#endif
 
 /* DWARF2 Abbreviation Glossary:
    CFA = Canonical Frame Address
@@ -82,6 +91,7 @@ int
 dwarf2out_do_frame ()
 {
   return (write_symbols == DWARF2_DEBUG
+         || write_symbols == VMS_AND_DWARF2_DEBUG
 #ifdef DWARF2_FRAME_INFO
          || DWARF2_FRAME_INFO
 #endif
@@ -92,6 +102,37 @@ dwarf2out_do_frame ()
          );
 }
 
+/* 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
+   compilation unit.  These numbers are used to create unique label id's
+   unique to each function definition.  */
+unsigned current_funcdef_number = 0;
+
+/* The size of the target's pointer type.  */
+#ifndef PTR_SIZE
+#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
+#endif
+
+/* Default version of targetm.eh_frame_section.  Note this must appear
+   outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro
+   guards.  */
+
+void
+default_eh_frame_section ()
+{
+#ifdef EH_FRAME_SECTION_NAME
+  named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
+#else
+  tree label = get_file_function_name ('F');
+
+  data_section ();
+  ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
+  ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
+  ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
+#endif
+}
+
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
 /* How to start an assembler comment.  */
@@ -141,7 +182,7 @@ typedef struct cfa_loc
 
 /* All call frame descriptions (FDE's) in the GCC generated DWARF
    refer to a single Common Information Entry (CIE), defined at
-   the beginning of the .debug_frame section.  This used of a single
+   the beginning of the .debug_frame section.  This use of a single
    CIE obviates the need to keep track of multiple CIE's
    in the DWARF generation routines below.  */
 
@@ -157,14 +198,9 @@ typedef struct dw_fde_struct
 }
 dw_fde_node;
 
-/* Maximum size (in bytes) of an artificially generated label.   */
+/* Maximum size (in bytes) of an artificially generated label.  */
 #define MAX_ARTIFICIAL_LABEL_BYTES     30
 
-/* The size of the target's pointer type.  */
-#ifndef PTR_SIZE
-#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
-#endif
-
 /* The size of addresses as they appear in the Dwarf 2 data.
    Some architectures use word addresses to refer to code locations,
    but Dwarf 2 info always uses byte addresses.  On such machines,
@@ -215,19 +251,22 @@ static unsigned fde_table_in_use;
 /* A list of call frame insns for the CIE.  */
 static dw_cfi_ref cie_cfi_head;
 
-/* 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
-   compilation unit.  These numbers are used to create unique label id's
-   unique to each function definition.  */
-unsigned current_funcdef_number = 0;
-
 /* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram
    attribute that accelerates the lookup of the FDE associated
    with the subprogram.  This variable holds the table index of the FDE
    associated with the current function (body) definition.  */
 static unsigned current_funcdef_fde;
 
+struct ht *debug_str_hash;
+
+struct indirect_string_node
+{
+  struct ht_identifier id;
+  unsigned int refcount;
+  unsigned int form;
+  char *label;
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static char *stripattributes           PARAMS ((const char *));
@@ -241,7 +280,7 @@ static void reg_save                        PARAMS ((const char *, unsigned,
                                                 unsigned, long));
 static void initial_return_save                PARAMS ((rtx));
 static long stack_adjust_offset                PARAMS ((rtx));
-static void output_cfi                 PARAMS ((dw_cfi_ref, dw_fde_ref));
+static void output_cfi                 PARAMS ((dw_cfi_ref, dw_fde_ref, int));
 static void output_call_frame_info     PARAMS ((int));
 static void dwarf2out_stack_adjust     PARAMS ((rtx));
 static void queue_reg_save             PARAMS ((const char *, rtx, long));
@@ -257,6 +296,11 @@ static struct dw_loc_descr_struct *build_cfa_loc
                                        PARAMS ((dw_cfa_location *));
 static void def_cfa_1                  PARAMS ((const char *, dw_cfa_location *));
 
+/* .debug_str support.  */
+static hashnode indirect_string_alloc  PARAMS ((hash_table *));
+static int output_indirect_string      PARAMS ((struct cpp_reader *,
+                                                hashnode, const PTR));
+
 /* How to start an assembler comment.  */
 #ifndef ASM_COMMENT_START
 #define ASM_COMMENT_START ";#"
@@ -271,20 +315,8 @@ static void def_cfa_1                      PARAMS ((const char *, dw_cfa_location *));
 #define SECTION_ASM_OP "\t.section\t"
 #endif
 
-/* The default format used by the ASM_OUTPUT_SECTION macro (see below) to
-   print the SECTION_ASM_OP and the section name.  The default here works for
-   almost all svr4 assemblers, except for the sparc, where the section name
-   must be enclosed in double quotes.  (See sparcv4.h).  */
-#ifndef SECTION_FORMAT
-#ifdef PUSHSECTION_FORMAT
-#define SECTION_FORMAT PUSHSECTION_FORMAT
-#else
-#define SECTION_FORMAT         "%s%s\n"
-#endif
-#endif
-
-#ifndef FRAME_SECTION
-#define FRAME_SECTION          ".debug_frame"
+#ifndef DEBUG_FRAME_SECTION
+#define DEBUG_FRAME_SECTION    ".debug_frame"
 #endif
 
 #ifndef FUNC_BEGIN_LABEL
@@ -293,6 +325,7 @@ static void def_cfa_1                       PARAMS ((const char *, dw_cfa_location *));
 #ifndef FUNC_END_LABEL
 #define FUNC_END_LABEL         "LFE"
 #endif
+#define FRAME_BEGIN_LABEL      "Lframe"
 #define CIE_AFTER_SIZE_LABEL   "LSCIE"
 #define CIE_END_LABEL          "LECIE"
 #define CIE_LENGTH_LABEL       "LLCIE"
@@ -310,11 +343,6 @@ static void def_cfa_1                      PARAMS ((const char *, dw_cfa_location *));
    output operations.  These may be overridden from within the tm.h file,
    but typically, that is unnecessary.  */
 
-#ifndef ASM_OUTPUT_SECTION
-#define ASM_OUTPUT_SECTION(FILE, SECTION) \
-  fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION)
-#endif
-
 #ifdef SET_ASM_OP
 #ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
 #define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO)            \
@@ -359,7 +387,7 @@ expand_builtin_dwarf_fp_regnum ()
 #ifndef INCOMING_FRAME_SP_OFFSET
 #define INCOMING_FRAME_SP_OFFSET 0
 #endif
-
+\f
 /* Return a pointer to a copy of the section string name S with all
    attributes stripped off, and an asterisk prepended (for assemble_name).  */
 
@@ -398,9 +426,7 @@ expand_builtin_init_dwarf_reg_sizes (address)
       if (offset < 0)
        continue;
 
-      emit_move_insn (change_address (mem, mode,
-                                     plus_constant (addr, offset)),
-                     GEN_INT (size));
+      emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
     }
 }
 
@@ -408,7 +434,7 @@ expand_builtin_init_dwarf_reg_sizes (address)
 
 static const char *
 dwarf_cfi_name (cfi_opc)
-     register unsigned cfi_opc;
+     unsigned cfi_opc;
 {
   switch (cfi_opc)
     {
@@ -473,7 +499,7 @@ dwarf_cfi_name (cfi_opc)
 static inline dw_cfi_ref
 new_cfi ()
 {
-  register dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
+  dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
 
   cfi->dw_cfi_next = NULL;
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
@@ -486,10 +512,10 @@ new_cfi ()
 
 static inline void
 add_cfi (list_head, cfi)
-     register dw_cfi_ref *list_head;
-     register dw_cfi_ref cfi;
+     dw_cfi_ref *list_head;
+     dw_cfi_ref cfi;
 {
-  register dw_cfi_ref *p;
+  dw_cfi_ref *p;
 
   /* Find the end of the chain.  */
   for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next)
@@ -517,12 +543,12 @@ dwarf2out_cfi_label ()
 
 static void
 add_fde_cfi (label, cfi)
-     register const char *label;
-     register dw_cfi_ref cfi;
+     const char *label;
+     dw_cfi_ref cfi;
 {
   if (label)
     {
-      register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
+      dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
 
       if (*label == 0)
        label = dwarf2out_cfi_label ();
@@ -530,7 +556,7 @@ add_fde_cfi (label, cfi)
       if (fde->dw_fde_current_label == NULL
          || strcmp (label, fde->dw_fde_current_label) != 0)
        {
-         register dw_cfi_ref xcfi;
+         dw_cfi_ref xcfi;
 
          fde->dw_fde_current_label = label = xstrdup (label);
 
@@ -552,8 +578,8 @@ add_fde_cfi (label, cfi)
 
 static inline void
 lookup_cfa_1 (cfi, loc)
-     register dw_cfi_ref cfi;
-     register dw_cfa_location *loc;
+     dw_cfi_ref cfi;
+     dw_cfa_location *loc;
 {
   switch (cfi->dw_cfi_opc)
     {
@@ -579,9 +605,9 @@ lookup_cfa_1 (cfi, loc)
 
 static void
 lookup_cfa (loc)
-     register dw_cfa_location *loc;
+     dw_cfa_location *loc;
 {
-  register dw_cfi_ref cfi;
+  dw_cfi_ref cfi;
 
   loc->reg = (unsigned long) -1;
   loc->offset = 0;
@@ -593,7 +619,7 @@ lookup_cfa (loc)
 
   if (fde_table_in_use)
     {
-      register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
+      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, loc);
     }
@@ -618,7 +644,7 @@ static long old_args_size;
 
 void
 dwarf2out_def_cfa (label, reg, offset)
-     register const char *label;
+     const char *label;
      unsigned reg;
      long offset;
 {
@@ -634,10 +660,10 @@ dwarf2out_def_cfa (label, reg, offset)
    the dw_cfa_location structure.  */
 static void
 def_cfa_1 (label, loc_p)
-     register const char *label;
+     const char *label;
      dw_cfa_location *loc_p;
 {
-  register dw_cfi_ref cfi;
+  dw_cfi_ref cfi;
   dw_cfa_location old_cfa, loc;
 
   cfa = *loc_p;
@@ -712,12 +738,12 @@ def_cfa_1 (label, loc_p)
 
 static void
 reg_save (label, reg, sreg, offset)
-     register const char *label;
-     register unsigned reg;
-     register unsigned sreg;
-     register long offset;
+     const char *label;
+     unsigned reg;
+     unsigned sreg;
+     long offset;
 {
-  register dw_cfi_ref cfi = new_cfi ();
+  dw_cfi_ref cfi = new_cfi ();
 
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
 
@@ -773,9 +799,9 @@ reg_save (label, reg, sreg, offset)
 
 void
 dwarf2out_window_save (label)
-     register const char *label;
+     const char *label;
 {
-  register dw_cfi_ref cfi = new_cfi ();
+  dw_cfi_ref cfi = new_cfi ();
   cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
   add_fde_cfi (label, cfi);
 }
@@ -788,7 +814,7 @@ dwarf2out_args_size (label, size)
      const char *label;
      long size;
 {
-  register dw_cfi_ref cfi;
+  dw_cfi_ref cfi;
 
   if (size == old_args_size)
     return;
@@ -805,9 +831,9 @@ dwarf2out_args_size (label, size)
 
 void
 dwarf2out_reg_save (label, reg, offset)
-     register const char *label;
-     register unsigned reg;
-     register long offset;
+     const char *label;
+     unsigned reg;
+     long offset;
 {
   reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
 }
@@ -817,8 +843,8 @@ dwarf2out_reg_save (label, reg, offset)
 
 void
 dwarf2out_return_save (label, offset)
-     register const char *label;
-     register long offset;
+     const char *label;
+     long offset;
 {
   reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset);
 }
@@ -828,8 +854,8 @@ dwarf2out_return_save (label, offset)
 
 void
 dwarf2out_return_reg (label, sreg)
-     register const char *label;
-     register unsigned sreg;
+     const char *label;
+     unsigned sreg;
 {
   reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0);
 }
@@ -839,7 +865,7 @@ dwarf2out_return_reg (label, sreg)
 
 static void
 initial_return_save (rtl)
-     register rtx rtl;
+     rtx rtl;
 {
   unsigned int reg = (unsigned int) -1;
   long offset = 0;
@@ -890,7 +916,7 @@ initial_return_save (rtl)
 }
 
 /* Given a SET, calculate the amount of stack adjustment it
-   contains. */
+   contains.  */
 
 static long
 stack_adjust_offset (pattern)
@@ -954,7 +980,8 @@ dwarf2out_stack_adjust (insn)
   long offset;
   const char *label;
 
-  if (! flag_non_call_exceptions && GET_CODE (insn) == CALL_INSN)
+  if (!flag_asynchronous_unwind_tables
+      && GET_CODE (insn) == CALL_INSN)
     {
       /* Extract the size of the args from the CALL rtx itself.  */
 
@@ -971,7 +998,7 @@ dwarf2out_stack_adjust (insn)
 
   /* If only calls can throw, and we have a frame pointer,
      save up adjustments until we see the CALL_INSN.  */
-  else if (! flag_non_call_exceptions
+  else if (!flag_asynchronous_unwind_tables
           && cfa.reg != STACK_POINTER_REGNUM)
     return;
 
@@ -994,7 +1021,7 @@ dwarf2out_stack_adjust (insn)
           || GET_CODE (PATTERN (insn)) == SEQUENCE)
     {
       /* There may be stack adjustments inside compound insns.  Search
-         for them. */
+         for them.  */
       int j;
 
       offset = 0;
@@ -1133,11 +1160,13 @@ static dw_cfa_location cfa_temp;
               cfa_store.reg to the actual CFA
   cfa_temp     register holding an integral value.  cfa_temp.offset
               stores the value, which will be used to adjust the
-              stack pointer.
+              stack pointer.  cfa_temp is also used like cfa_store,
+              to track stores to the stack via fp or a temp reg.
  
   Rules  1- 4: Setting a register's value to cfa.reg or an expression
               with cfa.reg as the first operand changes the cfa.reg and its
-              cfa.offset.
+              cfa.offset.  Rule 1 and 4 also set cfa_temp.reg and
+              cfa_temp.offset.
 
   Rules  6- 9: Set a non-cfa.reg register value to a constant or an
               expression yielding a constant.  This sets cfa_temp.reg
@@ -1146,9 +1175,9 @@ static dw_cfa_location cfa_temp;
   Rule 5:      Create a new register cfa_store used to save items to the
               stack.
 
-  Rules 10-13: Save a register to the stack.  Define offset as the
+  Rules 10-14: Save a register to the stack.  Define offset as the
               difference of the original location and cfa_store's
-              location.
+              location (or cfa_temp's location if cfa_temp is used).
 
   The Rules
 
@@ -1157,26 +1186,30 @@ static dw_cfa_location cfa_temp;
 
   Rule 1:
   (set <reg1> <reg2>:cfa.reg)
-  effects: cfa.reg = <REG1>
+  effects: cfa.reg = <reg1>
            cfa.offset unchanged
+          cfa_temp.reg = <reg1>
+          cfa_temp.offset = cfa.offset
 
   Rule 2:
-  (set sp ({minus,plus} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg}))
+  (set sp ({minus,plus,losum} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg}))
   effects: cfa.reg = sp if fp used
           cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
           cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
             if cfa_store.reg==sp
 
   Rule 3:
-  (set fp ({minus,plus} <reg>:cfa.reg <const_int>))
+  (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>))
   effects: cfa.reg = fp
           cfa_offset += +/- <const_int>
 
   Rule 4:
-  (set <reg1> (plus <reg2>:cfa.reg <const_int>))
+  (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>))
   constraints: <reg1> != fp
               <reg1> != sp
   effects: cfa.reg = <reg1>
+          cfa_temp.reg = <reg1>
+          cfa_temp.offset = cfa.offset
 
   Rule 5:
   (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
@@ -1208,30 +1241,31 @@ static dw_cfa_location cfa_temp;
   (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
   effects: cfa_store.offset -= <const_int>
           cfa.offset = cfa_store.offset if cfa.reg == sp
-          offset = -cfa_store.offset
           cfa.reg = sp
-          cfa.base_offset = offset
+          cfa.base_offset = -cfa_store.offset
 
   Rule 11:
   (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>)
   effects: cfa_store.offset += -/+ mode_size(mem)
           cfa.offset = cfa_store.offset if cfa.reg == sp
-          offset = -cfa_store.offset
           cfa.reg = sp
-          cfa.base_offset = offset
+          cfa.base_offset = -cfa_store.offset
 
   Rule 12:
-  (set (mem ({minus,plus} <reg1>:cfa_store <const_int>)) <reg2>)
-  effects: cfa_store.offset += -/+ <const_int>
-          offset = -cfa_store.offset
-          cfa.reg = <reg1
-          cfa.base_offset = offset
+  (set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>)) <reg2>)
+  effects: cfa.reg = <reg1>
+          cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset
 
   Rule 13:
-  (set (mem <reg1>:cfa_store) <reg2>)
-  effects: offset = -cfa_store.offset
-          cfa.reg = <reg1>
-          cfa.base_offset = offset */
+  (set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>)
+  effects: cfa.reg = <reg1>
+          cfa.base_offset = -{cfa_store,cfa_temp}.offset
+
+  Rule 14:
+  (set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>)
+  effects: cfa.reg = <reg1>
+          cfa.base_offset = -cfa_temp.offset
+          cfa_temp.offset -= mode_size(mem)  */
 
 static void
 dwarf2out_frame_debug_expr (expr, label)
@@ -1291,10 +1325,13 @@ dwarf2out_frame_debug_expr (expr, label)
             FP.  So we just rely on the backends to only set
             RTX_FRAME_RELATED_P on appropriate insns.  */
          cfa.reg = REGNO (dest);
+         cfa_temp.reg = cfa.reg;
+         cfa_temp.offset = cfa.offset;
          break;
 
        case PLUS:
        case MINUS:
+       case LO_SUM:
          if (dest == stack_pointer_rtx)
            {
              /* Rule 2 */
@@ -1320,10 +1357,13 @@ dwarf2out_frame_debug_expr (expr, label)
                    abort ();
                  cfa.reg = STACK_POINTER_REGNUM;
                }
+             else if (GET_CODE (src) == LO_SUM)
+               /* Assume we've set the source reg of the LO_SUM from sp.  */
+               ;
              else if (XEXP (src, 0) != stack_pointer_rtx)
                abort ();
 
-             if (GET_CODE (src) == PLUS)
+             if (GET_CODE (src) != MINUS)
                offset = -offset;
              if (cfa.reg == STACK_POINTER_REGNUM)
                cfa.offset += offset;
@@ -1343,7 +1383,7 @@ dwarf2out_frame_debug_expr (expr, label)
                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
                {
                  offset = INTVAL (XEXP (src, 1));
-                 if (GET_CODE (src) == PLUS)
+                 if (GET_CODE (src) != MINUS)
                    offset = -offset;
                  cfa.offset += offset;
                  cfa.reg = HARD_FRAME_POINTER_REGNUM;
@@ -1353,7 +1393,7 @@ dwarf2out_frame_debug_expr (expr, label)
            }
          else
            {
-             if (GET_CODE (src) != PLUS)
+             if (GET_CODE (src) == MINUS)
                abort ();
 
              /* Rule 4 */
@@ -1363,27 +1403,34 @@ dwarf2out_frame_debug_expr (expr, label)
                {
                  /* Setting a temporary CFA register that will be copied
                     into the FP later on.  */
-                 offset = INTVAL (XEXP (src, 1));
-                 if (GET_CODE (src) == PLUS)
-                   offset = -offset;
+                 offset = - INTVAL (XEXP (src, 1));
                  cfa.offset += offset;
                  cfa.reg = REGNO (dest);
+                 /* Or used to save regs to the stack.  */
+                 cfa_temp.reg = cfa.reg;
+                 cfa_temp.offset = cfa.offset;
                }
              /* Rule 5 */
-             else
+             else if (GET_CODE (XEXP (src, 0)) == REG
+                      && REGNO (XEXP (src, 0)) == cfa_temp.reg
+                      && XEXP (src, 1) == stack_pointer_rtx)
                {
                  /* Setting a scratch register that we will use instead
                     of SP for saving registers to the stack.  */
-                 if (XEXP (src, 1) != stack_pointer_rtx)
-                   abort ();
-                 if (GET_CODE (XEXP (src, 0)) != REG
-                     || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg)
-                   abort ();
                  if (cfa.reg != STACK_POINTER_REGNUM)
                    abort ();
                  cfa_store.reg = REGNO (dest);
                  cfa_store.offset = cfa.offset - cfa_temp.offset;
                }
+             /* Rule 9 */
+             else if (GET_CODE (src) == LO_SUM
+                      && GET_CODE (XEXP (src, 1)) == CONST_INT)
+               {
+                 cfa_temp.reg = REGNO (dest);
+                 cfa_temp.offset = INTVAL (XEXP (src, 1));
+               }
+             else
+               abort ();
            }
          break;
 
@@ -1404,26 +1451,18 @@ dwarf2out_frame_debug_expr (expr, label)
          cfa_temp.offset |= INTVAL (XEXP (src, 1));
          break;
 
+         /* Skip over HIGH, assuming it will be followed by a LO_SUM,
+            which will fill in all of the bits.  */
+         /* Rule 8 */
+       case HIGH:
+         break;
+
        default:
          abort ();
        }
       def_cfa_1 (label, &cfa);
       break;
 
-      /* Skip over HIGH, assuming it will be followed by a LO_SUM, which
-        will fill in all of the bits.  */
-      /* Rule 8 */
-    case HIGH:
-      break;
-
-      /* Rule 9 */
-    case LO_SUM:
-      if (GET_CODE (XEXP (src, 1)) != CONST_INT)
-       abort ();
-      cfa_temp.reg = REGNO (dest);
-      cfa_temp.offset = INTVAL (XEXP (src, 1));
-      break;
-
     case MEM:
       if (GET_CODE (src) != REG)
        abort ();
@@ -1470,23 +1509,38 @@ dwarf2out_frame_debug_expr (expr, label)
          /* With an offset.  */
        case PLUS:
        case MINUS:
+       case LO_SUM:
          if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT)
            abort ();
          offset = INTVAL (XEXP (XEXP (dest, 0), 1));
          if (GET_CODE (XEXP (dest, 0)) == MINUS)
            offset = -offset;
 
-         if (cfa_store.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+         if (cfa_store.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+           offset -= cfa_store.offset;
+         else if (cfa_temp.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+           offset -= cfa_temp.offset;
+         else
            abort ();
-         offset -= cfa_store.offset;
          break;
 
          /* Rule 13 */
          /* Without an offset.  */
        case REG:
-         if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0)))
+         if (cfa_store.reg == (unsigned) REGNO (XEXP (dest, 0)))
+           offset = -cfa_store.offset;
+         else if (cfa_temp.reg == (unsigned) REGNO (XEXP (dest, 0)))
+           offset = -cfa_temp.offset;
+         else
            abort ();
-         offset = -cfa_store.offset;
+         break;
+
+         /* Rule 14 */
+       case POST_INC:
+         if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+           abort ();
+         offset = -cfa_temp.offset;
+         cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
          break;
 
        default:
@@ -1587,9 +1641,10 @@ dwarf2out_frame_debug (insn)
 /* Output a Call Frame Information opcode and its operand(s).  */
 
 static void
-output_cfi (cfi, fde)
-     register dw_cfi_ref cfi;
-     register dw_fde_ref fde;
+output_cfi (cfi, fde, for_eh)
+     dw_cfi_ref cfi;
+     dw_fde_ref fde;
+     int for_eh;
 {
   if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
     {
@@ -1621,8 +1676,14 @@ output_cfi (cfi, fde)
       switch (cfi->dw_cfi_opc)
        {
        case DW_CFA_set_loc:
-         dw2_asm_output_addr (DWARF2_ADDR_SIZE, 
-                              cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
+         if (for_eh)
+           dw2_asm_output_encoded_addr_rtx (
+               ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0),
+               gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr),
+               NULL);
+         else
+           dw2_asm_output_addr (DWARF2_ADDR_SIZE,
+                                cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
          break;
        case DW_CFA_advance_loc1:
          dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr,
@@ -1683,18 +1744,22 @@ static void
 output_call_frame_info (for_eh)
      int for_eh;
 {
-  register unsigned long i;
-  register dw_fde_ref fde;
-  register dw_cfi_ref cfi;
-  char l1[20], l2[20];
+  unsigned int i;
+  dw_fde_ref fde;
+  dw_cfi_ref cfi;
+  char l1[20], l2[20], section_start_label[20];
   int any_lsda_needed = 0;
   char augmentation[6];
+  int augmentation_size;
+  int fde_encoding = DW_EH_PE_absptr;
+  int per_encoding = DW_EH_PE_absptr;
+  int lsda_encoding = DW_EH_PE_absptr;
 
   /* If we don't have any functions we'll want to unwind out of, don't
      emit any EH unwind information.  */
   if (for_eh)
     {
-      int any_eh_needed = 0;
+      int any_eh_needed = flag_asynchronous_unwind_tables;
       for (i = 0; i < fde_table_in_use; ++i)
        if (fde_table[i].uses_eh_lsda)
          any_eh_needed = any_lsda_needed = 1;
@@ -1710,21 +1775,12 @@ output_call_frame_info (for_eh)
     app_enable ();
 
   if (for_eh)
-    {
-#ifdef EH_FRAME_SECTION
-      EH_FRAME_SECTION ();
-#else
-      tree label = get_file_function_name ('F');
-
-      force_data_section ();
-      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE));
-      ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
-      ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
-#endif
-      assemble_label ("__FRAME_BEGIN__");
-    }
+    (*targetm.asm_out.eh_frame_section) ();
   else
-    ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
+    named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG);
+
+  ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh);
+  ASM_OUTPUT_LABEL (asm_out_file, section_start_label);
 
   /* Output the CIE.  */
   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
@@ -1742,20 +1798,68 @@ output_call_frame_info (for_eh)
   dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version");
 
   augmentation[0] = 0;
+  augmentation_size = 0;
   if (for_eh)
     {
+      char *p;
+
       /* Augmentation:
         z      Indicates that a uleb128 is present to size the
                augmentation section.
-        R      Indicates a pointer encoding for CIE and FDE pointers.
-        P      Indicates the presence of a language personality
-               routine in the CIE augmentation and an LSDA in the
-               FDE augmentation.  */
-
-      /* ??? Handle pointer encodings.  */
-
+        L      Indicates the encoding (and thus presence) of
+               an LSDA pointer in the FDE augmentation.
+        R      Indicates a non-default pointer encoding for
+               FDE code pointers.
+        P      Indicates the presence of an encoding + language
+               personality routine in the CIE augmentation.  */
+
+      fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+      per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
+      lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
+
+      p = augmentation + 1;
+      if (eh_personality_libfunc)
+       {
+         *p++ = 'P';
+         augmentation_size += 1 + size_of_encoded_value (per_encoding);
+       }
       if (any_lsda_needed)
-       strcpy (augmentation, "zP");
+       {
+         *p++ = 'L';
+         augmentation_size += 1;
+       }
+      if (fde_encoding != DW_EH_PE_absptr)
+       {
+         *p++ = 'R';
+         augmentation_size += 1;
+       }
+      if (p > augmentation + 1)
+       {
+         augmentation[0] = 'z';
+          *p = '\0';
+       }
+
+      /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
+      if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
+       {
+         int offset = (  4             /* Length */
+                       + 4             /* CIE Id */
+                       + 1             /* CIE version */
+                       + strlen (augmentation) + 1     /* Augmentation */
+                       + size_of_uleb128 (1)           /* Code alignment */
+                       + size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT)
+                       + 1             /* RA column */
+                       + 1             /* Augmentation size */
+                       + 1             /* Personality encoding */ );
+         int pad = -offset & (PTR_SIZE - 1);
+
+         augmentation_size += pad;
+
+         /* Augmentations should be small, so there's scarce need to
+            iterate for a solution.  Die if we exceed one uleb128 byte.  */
+         if (size_of_uleb128 (augmentation_size) != 1)
+           abort ();
+       }
     }
   dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation");
 
@@ -1768,19 +1872,28 @@ output_call_frame_info (for_eh)
 
   if (augmentation[0])
     {
-      dw2_asm_output_data_uleb128 (DWARF2_ADDR_SIZE, "Augmentation size");
+      dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
       if (eh_personality_libfunc)
-       dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, eh_personality_libfunc,
-                                "Personality");
-      else
-       dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, "Personality (none)");
+       {
+         dw2_asm_output_data (1, per_encoding, "Personality (%s)",
+                              eh_data_format_name (per_encoding));
+         dw2_asm_output_encoded_addr_rtx (per_encoding,
+                                          eh_personality_libfunc, NULL);
+       }
+      if (any_lsda_needed)
+       dw2_asm_output_data (1, lsda_encoding, "LSDA Encoding (%s)",
+                            eh_data_format_name (lsda_encoding));
+      if (fde_encoding != DW_EH_PE_absptr)
+       dw2_asm_output_data (1, fde_encoding, "FDE Encoding (%s)",
+                            eh_data_format_name (fde_encoding));
     }
 
   for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
-    output_cfi (cfi, NULL);
+    output_cfi (cfi, NULL, for_eh);
 
   /* Pad the CIE out to an address sized boundary.  */
-  ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE));
+  ASM_OUTPUT_ALIGN (asm_out_file, 
+                   floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE));
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 
   /* Loop through all of the FDE's.  */
@@ -1799,54 +1912,84 @@ output_call_frame_info (for_eh)
                            "FDE Length");
       ASM_OUTPUT_LABEL (asm_out_file, l1);
 
-      /* ??? This always emits a 4 byte offset when for_eh is true, but it
-        emits a target dependent sized offset when for_eh is not true.
-        This inconsistency may confuse gdb.  The only case where we need a
-        non-4 byte offset is for the Irix6 N64 ABI, so we may lose SGI
-        compatibility if we emit a 4 byte offset.  We need a 4 byte offset
-        though in order to be compatible with the dwarf_fde struct in frame.c.
-        If the for_eh case is changed, then the struct in frame.c has
-        to be adjusted appropriately.  */
       if (for_eh)
-       dw2_asm_output_delta (4, l1, "__FRAME_BEGIN__", "FDE CIE offset");
+       dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset");
       else
-       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
-                              stripattributes (FRAME_SECTION),
+       dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label,
                               "FDE CIE offset");
 
-      dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
-                          "FDE initial location");
-
-      dw2_asm_output_delta (DWARF2_ADDR_SIZE, fde->dw_fde_end,
-                           fde->dw_fde_begin, "FDE address range");
+      if (for_eh)
+       {
+         dw2_asm_output_encoded_addr_rtx (fde_encoding,
+                  gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
+                  "FDE initial location");
+         dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
+                               fde->dw_fde_end, fde->dw_fde_begin, 
+                               "FDE address range");
+       }
+      else
+       {
+         dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
+                              "FDE initial location");
+         dw2_asm_output_delta (DWARF2_ADDR_SIZE, 
+                               fde->dw_fde_end, fde->dw_fde_begin, 
+                               "FDE address range");
+       }
 
       if (augmentation[0])
        {
-         dw2_asm_output_data_uleb128 (DWARF2_ADDR_SIZE, "Augmentation size");
-
-         if (fde->uses_eh_lsda)
+         if (any_lsda_needed)
            {
-             ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", fde->funcdef_number);
-             dw2_asm_output_offset (DWARF2_ADDR_SIZE, l1,
-                                    "Language Specific Data Area");
+             int size = size_of_encoded_value (lsda_encoding);
+
+             if (lsda_encoding == DW_EH_PE_aligned)
+               {
+                 int offset = (  4             /* Length */
+                               + 4             /* CIE offset */
+                               + 2 * size_of_encoded_value (fde_encoding)
+                               + 1             /* Augmentation size */ );
+                 int pad = -offset & (PTR_SIZE - 1);
+
+                 size += pad;
+                 if (size_of_uleb128 (size) != 1)
+                   abort ();
+               }
+
+             dw2_asm_output_data_uleb128 (size, "Augmentation size");
+
+             if (fde->uses_eh_lsda)
+               {
+                 ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA",
+                                              fde->funcdef_number);
+                 dw2_asm_output_encoded_addr_rtx (
+                       lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1),
+                       "Language Specific Data Area");
+               }
+             else
+               {
+                 if (lsda_encoding == DW_EH_PE_aligned)
+                   ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
+                 dw2_asm_output_data (size_of_encoded_value (lsda_encoding),
+                                      0, "Language Specific Data Area (none)");
+               }
            }
          else
-           dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
-                                "Language Specific Data Area (none)");
+           dw2_asm_output_data_uleb128 (0, "Augmentation size");
        }
 
       /* 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, for_eh);
 
       /* Pad the FDE out to an address sized boundary.  */
-      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE));
+      ASM_OUTPUT_ALIGN (asm_out_file, 
+                       floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
       ASM_OUTPUT_LABEL (asm_out_file, l2);
     }
 
-#ifndef EH_FRAME_SECTION
+#ifndef EH_FRAME_SECTION_NAME
   if (for_eh)
     dw2_asm_output_data (4, 0, "End of Table");
 #endif
@@ -1865,19 +2008,42 @@ output_call_frame_info (for_eh)
    the prologue.  */
 
 void
-dwarf2out_begin_prologue ()
+dwarf2out_begin_prologue (line, file)
+     unsigned int line ATTRIBUTE_UNUSED;
+     const char *file ATTRIBUTE_UNUSED;
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
-  register dw_fde_ref fde;
+  dw_fde_ref fde;
+
+  current_function_func_begin_label = 0;
+
+#ifdef IA64_UNWIND_INFO
+  /* ??? current_function_func_begin_label is also used by except.c
+     for call-site information.  We must emit this label if it might
+     be used.  */
+  if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS)
+      && ! dwarf2out_do_frame ())
+    return;
+#else
+  if (! dwarf2out_do_frame ())
+    return;
+#endif
 
   ++current_funcdef_number;
 
   function_section (current_function_decl);
   ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
                               current_funcdef_number);
-  ASM_OUTPUT_LABEL (asm_out_file, label);
+  ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
+                         current_funcdef_number);
   current_function_func_begin_label = get_identifier (label);
 
+#ifdef IA64_UNWIND_INFO
+  /* We can elide the fde allocation if we're not emitting debug info.  */
+  if (! dwarf2out_do_frame ())
+    return;
+#endif
+
   /* Expand the fde table if necessary.  */
   if (fde_table_in_use == fde_table_allocated)
     {
@@ -1901,6 +2067,13 @@ dwarf2out_begin_prologue ()
   fde->uses_eh_lsda = cfun->uses_eh_lsda;
 
   args_size = old_args_size = 0;
+
+  /* We only want to output line number information for the genuine
+     dwarf2 prologue case, not the eh frame case.  */
+#ifdef DWARF2_DEBUGGING_INFO
+  if (file)
+    dwarf2out_source_line (line, file);
+#endif
 }
 
 /* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -1943,16 +2116,10 @@ void
 dwarf2out_frame_finish ()
 {
   /* Output call frame information.  */
-#ifdef MIPS_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG)
+  if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
     output_call_frame_info (0);
-  if (flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS))
-    output_call_frame_info (1);
-#else
-  if (write_symbols == DWARF2_DEBUG
-      || flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS))
+  if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
     output_call_frame_info (1);
-#endif
 }
 \f
 /* And now, the subset of the debugging information support code necessary
@@ -1961,6 +2128,7 @@ dwarf2out_frame_finish ()
 typedef struct dw_val_struct *dw_val_ref;
 typedef struct die_struct *dw_die_ref;
 typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
+typedef struct dw_loc_list_struct *dw_loc_list_ref;
 
 /* Each DIE may have a series of attribute/value pairs.  Values
    can take on several forms.  The forms that are used in this
@@ -1969,7 +2137,10 @@ typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
 typedef enum
 {
   dw_val_class_addr,
+  dw_val_class_offset,
   dw_val_class_loc,
+  dw_val_class_loc_list,
+  dw_val_class_range_list,
   dw_val_class_const,
   dw_val_class_unsigned_const,
   dw_val_class_long_long,
@@ -2011,6 +2182,8 @@ typedef struct dw_val_struct
   union
     {
       rtx val_addr;
+      long unsigned val_offset;
+      dw_loc_list_ref  val_loc_list;
       dw_loc_descr_ref val_loc;
       long int val_int;
       long unsigned val_unsigned;
@@ -2021,7 +2194,7 @@ typedef struct dw_val_struct
        int external;
       } val_die_ref;
       unsigned val_fde_index;
-      char *val_str;
+      struct indirect_string_node *val_str;
       char *val_lbl_id;
       unsigned char val_flag;
     }
@@ -2042,6 +2215,19 @@ typedef struct dw_loc_descr_struct
 }
 dw_loc_descr_node;
 
+/* Location lists are ranges + location descriptions for that range,
+   so you can track variables that are in different places over
+   their entire life.  */
+typedef struct dw_loc_list_struct
+{
+  dw_loc_list_ref dw_loc_next;
+  const char *begin; /* Label for begin address of range */
+  const char *end;  /* Label for end address of range */
+  char *ll_symbol; /* Label for beginning of location list. Only on head of list */
+  const char *section; /* Section this loclist is relative to */
+  dw_loc_descr_ref expr;
+} dw_loc_list_node;
+
 static const char *dwarf_stack_op_name PARAMS ((unsigned));
 static dw_loc_descr_ref new_loc_descr  PARAMS ((enum dwarf_location_atom,
                                                 unsigned long,
@@ -2057,7 +2243,7 @@ static void output_loc_sequence           PARAMS ((dw_loc_descr_ref));
 
 static const char *
 dwarf_stack_op_name (op)
-     register unsigned op;
+     unsigned op;
 {
   switch (op)
     {
@@ -2362,13 +2548,13 @@ dwarf_stack_op_name (op)
 
 static inline dw_loc_descr_ref
 new_loc_descr (op, oprnd1, oprnd2)
-     register enum dwarf_location_atom op;
-     register unsigned long oprnd1;
-     register unsigned long oprnd2;
+     enum dwarf_location_atom op;
+     unsigned long oprnd1;
+     unsigned long oprnd2;
 {
   /* Use xcalloc here so we clear out all of the long_long constant in
      the union.  */
-  register dw_loc_descr_ref descr
+  dw_loc_descr_ref descr
     = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node));
 
   descr->dw_loc_opc = op;
@@ -2380,14 +2566,15 @@ new_loc_descr (op, oprnd1, oprnd2)
   return descr;
 }
 
+
 /* Add a location description term to a location description expression.  */
 
 static inline void
 add_loc_descr (list_head, descr)
-     register dw_loc_descr_ref *list_head;
-     register dw_loc_descr_ref descr;
+     dw_loc_descr_ref *list_head;
+     dw_loc_descr_ref descr;
 {
-  register dw_loc_descr_ref *d;
+  dw_loc_descr_ref *d;
 
   /* Find the end of the chain.  */
   for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
@@ -2400,9 +2587,9 @@ add_loc_descr (list_head, descr)
 
 static unsigned long
 size_of_loc_descr (loc)
-     register dw_loc_descr_ref loc;
+     dw_loc_descr_ref loc;
 {
-  register unsigned long size = 1;
+  unsigned long size = 1;
 
   switch (loc->dw_loc_opc)
     {
@@ -2503,9 +2690,9 @@ size_of_loc_descr (loc)
 
 static unsigned long
 size_of_locs (loc)
-     register dw_loc_descr_ref loc;
+     dw_loc_descr_ref loc;
 {
-  register unsigned long size = 0;
+  unsigned long size = 0;
 
   for (; loc != NULL; loc = loc->dw_loc_next)
     {
@@ -2520,10 +2707,10 @@ size_of_locs (loc)
 
 static void
 output_loc_operands (loc)
-     register dw_loc_descr_ref loc;
+     dw_loc_descr_ref loc;
 {
-  register dw_val_ref val1 = &loc->dw_loc_oprnd1;
-  register dw_val_ref val2 = &loc->dw_loc_oprnd2;
+  dw_val_ref val1 = &loc->dw_loc_oprnd1;
+  dw_val_ref val2 = &loc->dw_loc_oprnd2;
 
   switch (loc->dw_loc_opc)
     {
@@ -2683,7 +2870,7 @@ output_cfa_loc (cfi)
   output_loc_sequence (loc);
 }
 
-/* This function builds a dwarf location descriptor seqeunce from
+/* This function builds a dwarf location descriptor sequence from
    a dw_cfa_location.  */
 
 static struct dw_loc_descr_struct *
@@ -2819,7 +3006,7 @@ get_cfa_from_loc_descr (cfa, loc)
          cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
          break;
        default:
-         internal_error ("DW_LOC_OP %s not implememnted\n",
+         internal_error ("DW_LOC_OP %s not implemented\n",
                          dwarf_stack_op_name (ptr->dw_loc_opc));
        }
     }
@@ -2829,6 +3016,47 @@ get_cfa_from_loc_descr (cfa, loc)
 /* And now, the support for symbolic debugging information.  */
 #ifdef DWARF2_DEBUGGING_INFO
 
+static void dwarf2out_init             PARAMS ((const char *));
+static void dwarf2out_finish           PARAMS ((const char *));
+static void dwarf2out_define           PARAMS ((unsigned int, const char *));
+static void dwarf2out_undef            PARAMS ((unsigned int, const char *));
+static void dwarf2out_start_source_file        PARAMS ((unsigned, const char *));
+static void dwarf2out_end_source_file  PARAMS ((unsigned));
+static void dwarf2out_begin_block      PARAMS ((unsigned, unsigned));
+static void dwarf2out_end_block                PARAMS ((unsigned, unsigned));
+static bool dwarf2out_ignore_block     PARAMS ((tree));
+static void dwarf2out_global_decl      PARAMS ((tree));
+static void dwarf2out_abstract_function PARAMS ((tree));
+
+/* The debug hooks structure.  */
+
+struct gcc_debug_hooks dwarf2_debug_hooks =
+{
+  dwarf2out_init,
+  dwarf2out_finish,
+  dwarf2out_define,
+  dwarf2out_undef,
+  dwarf2out_start_source_file,
+  dwarf2out_end_source_file,
+  dwarf2out_begin_block,
+  dwarf2out_end_block,
+  dwarf2out_ignore_block,
+  dwarf2out_source_line,
+  dwarf2out_begin_prologue,
+  debug_nothing_int,           /* end_prologue */
+  dwarf2out_end_epilogue,
+  debug_nothing_tree,          /* begin_function */
+  debug_nothing_int,           /* end_function */
+  dwarf2out_decl,              /* function_decl */
+  dwarf2out_global_decl,
+  debug_nothing_tree,          /* deferred_inline_function */
+  /* The DWARF 2 backend tries to reduce debugging bloat by not
+     emitting the abstract description of inline functions until
+     something tries to reference them.  */
+  dwarf2out_abstract_function, /* outlining_inline_function */
+  debug_nothing_rtx            /* label */
+};
+\f
 /* NOTE: In the comments in this file, many references are made to
    "Debugging Information Entries".  This term is abbreviated as `DIE'
    throughout the remainder of this file.  */
@@ -2849,7 +3077,7 @@ typedef struct dw_attr_struct *dw_attr_ref;
 typedef struct dw_line_info_struct *dw_line_info_ref;
 typedef struct dw_separate_line_info_struct *dw_separate_line_info_ref;
 typedef struct pubname_struct *pubname_ref;
-typedef dw_die_ref *arange_ref;
+typedef struct dw_ranges_struct *dw_ranges_ref;
 
 /* Each entry in the line_info_table maintains the file and
    line number associated with the label generated for that
@@ -2910,6 +3138,11 @@ typedef struct pubname_struct
 }
 pubname_entry;
 
+struct dw_ranges_struct
+{
+  int block_num;
+};
+
 /* The limbo die list structure.  */
 typedef struct limbo_die_struct
 {
@@ -2993,7 +3226,7 @@ extern int flag_traditional;
    This value was chosen to give a reasonable range of values.  */
 #define DWARF_LINE_BASE  -10
 
-/* First special line opcde - leave room for the standard opcodes.  */
+/* First special line opcode - leave room for the standard opcodes.  */
 #define DWARF_LINE_OPCODE_BASE  10
 
 /* Range of line offsets in a special line info. opcode.  */
@@ -3055,17 +3288,7 @@ static unsigned decl_die_table_in_use;
    of declaration scopes at the current scope and containing
    scopes.  This table is used to find the proper place to
    define type declaration DIE's.  */
-static tree *decl_scope_table;
-
-/* Number of elements currently allocated for the decl_scope_table.  */
-static int decl_scope_table_allocated;
-
-/* Current level of nesting of declaration scopes.  */
-static int decl_scope_depth;
-
-/* Size (in elements) of increments by which we may expand the
-   decl_scope_table.  */
-#define DECL_SCOPE_TABLE_INCREMENT 64
+varray_type decl_scope_table;
 
 /* A pointer to the base of a list of references to DIE's that
    are uniquely identified by their tag, presence/absence of
@@ -3120,9 +3343,8 @@ static unsigned pubname_table_in_use;
    pubname_table.  */
 #define PUBNAME_TABLE_INCREMENT 64
 
-/* A pointer to the base of a table that contains a list of publicly
-   accessible names.  */
-static arange_ref arange_table;
+/* Array of dies for which we should generate .debug_arange info.  */
+static dw_die_ref *arange_table;
 
 /* Number of elements currently allocated for arange_table.  */
 static unsigned arange_table_allocated;
@@ -3134,21 +3356,28 @@ static unsigned arange_table_in_use;
    arange_table.  */
 #define ARANGE_TABLE_INCREMENT 64
 
-/* A pointer to the base of a list of incomplete types which might be
-   completed at some later time.  */
+/* Array of dies for which we should generate .debug_ranges info.  */
+static dw_ranges_ref ranges_table;
+
+/* Number of elements currently allocated for ranges_table.  */
+static unsigned ranges_table_allocated;
 
-static tree *incomplete_types_list;
+/* Number of elements in ranges_table currently in use.  */
+static unsigned ranges_table_in_use;
 
-/* Number of elements currently allocated for the incomplete_types_list.  */
-static unsigned incomplete_types_allocated;
+/* Size (in elements) of increments by which we may expand the
+   ranges_table.  */
+#define RANGES_TABLE_INCREMENT 64
 
-/* Number of elements of incomplete_types_list currently in use.  */
-static unsigned incomplete_types;
+/* Whether we have location lists that need outputting */
+static unsigned have_location_lists;
 
-/* Size (in elements) of increments by which we may expand the incomplete
-   types list.  Actually, a single hunk of space of this size should
-   be enough for most typical programs.         */
-#define INCOMPLETE_TYPES_INCREMENT 64
+/* A pointer to the base of a list of incomplete types which might be
+   completed at some later time.  incomplete_types_list needs to be a VARRAY
+   because we want to tell the garbage collector about it.  If we don't tell
+   the garbage collector about it, we can garbage collect live data.
+   Bug 4215.*/
+varray_type incomplete_types;
 
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
@@ -3204,6 +3433,9 @@ static void add_AT_fde_ref                PARAMS ((dw_die_ref,
 static void add_AT_loc                 PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute,
                                                 dw_loc_descr_ref));
+static void add_AT_loc_list            PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                dw_loc_list_ref));
 static void add_AT_addr                        PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute,
                                                 rtx));
@@ -3213,6 +3445,12 @@ static void add_AT_lbl_id                PARAMS ((dw_die_ref,
 static void add_AT_lbl_offset          PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute,
                                                 const char *));
+static void add_AT_offset              PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned long));
+static void add_AT_range_list          PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned long));
 static dw_attr_ref get_AT              PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute));
 static const char *get_AT_low_pc       PARAMS ((dw_die_ref));
@@ -3226,6 +3464,7 @@ static unsigned get_AT_unsigned           PARAMS ((dw_die_ref,
 static inline dw_die_ref get_AT_ref    PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute));
 static int is_c_family                 PARAMS ((void));
+static int is_cxx                      PARAMS ((void));
 static int is_java                     PARAMS ((void));
 static int is_fortran                  PARAMS ((void));
 static void remove_AT                  PARAMS ((dw_die_ref,
@@ -3251,12 +3490,11 @@ static void compute_section_prefix      PARAMS ((dw_die_ref));
 static int is_type_die                 PARAMS ((dw_die_ref));
 static int is_comdat_die               PARAMS ((dw_die_ref));
 static int is_symbol_die               PARAMS ((dw_die_ref));
-static char *gen_internal_sym          PARAMS ((void));
 static void assign_symbol_names                PARAMS ((dw_die_ref));
 static void break_out_includes         PARAMS ((dw_die_ref));
 static void add_sibling_attributes     PARAMS ((dw_die_ref));
 static void build_abbrev_table         PARAMS ((dw_die_ref));
-static unsigned long size_of_string    PARAMS ((const char *));
+static void output_location_lists      PARAMS ((dw_die_ref));
 static int constant_size               PARAMS ((long unsigned));
 static unsigned long size_of_die       PARAMS ((dw_die_ref));
 static void calc_die_sizes             PARAMS ((dw_die_ref));
@@ -3276,6 +3514,8 @@ static void add_pubname                   PARAMS ((tree, dw_die_ref));
 static void output_pubnames            PARAMS ((void));
 static void add_arange                 PARAMS ((tree, dw_die_ref));
 static void output_aranges             PARAMS ((void));
+static unsigned int add_ranges         PARAMS ((tree));
+static void output_ranges              PARAMS ((void));
 static void output_line_info           PARAMS ((void));
 static void output_file_names           PARAMS ((void));
 static dw_die_ref base_type_die                PARAMS ((tree));
@@ -3367,58 +3607,80 @@ static void gen_type_die_for_member     PARAMS ((tree, tree, dw_die_ref));
 static rtx save_rtx                    PARAMS ((rtx));
 static void splice_child_die           PARAMS ((dw_die_ref, dw_die_ref));
 static int file_info_cmp               PARAMS ((const void *, const void *));
+static dw_loc_list_ref new_loc_list     PARAMS ((dw_loc_descr_ref, 
+                                                const char *, const char *,
+                                                const char *, unsigned));
+static void add_loc_descr_to_loc_list   PARAMS ((dw_loc_list_ref *,
+                                                dw_loc_descr_ref,
+                                                const char *, const char *, const char *));
+static void output_loc_list            PARAMS ((dw_loc_list_ref));
+static char *gen_internal_sym          PARAMS ((const char *));
 
 /* Section names used to hold DWARF debugging information.  */
 #ifndef DEBUG_INFO_SECTION
 #define DEBUG_INFO_SECTION     ".debug_info"
 #endif
-#ifndef ABBREV_SECTION
-#define ABBREV_SECTION         ".debug_abbrev"
+#ifndef DEBUG_ABBREV_SECTION
+#define DEBUG_ABBREV_SECTION   ".debug_abbrev"
 #endif
-#ifndef ARANGES_SECTION
-#define ARANGES_SECTION                ".debug_aranges"
+#ifndef DEBUG_ARANGES_SECTION
+#define DEBUG_ARANGES_SECTION  ".debug_aranges"
 #endif
-#ifndef DW_MACINFO_SECTION
-#define DW_MACINFO_SECTION     ".debug_macinfo"
+#ifndef DEBUG_MACINFO_SECTION
+#define DEBUG_MACINFO_SECTION  ".debug_macinfo"
 #endif
 #ifndef DEBUG_LINE_SECTION
 #define DEBUG_LINE_SECTION     ".debug_line"
 #endif
-#ifndef LOC_SECTION
-#define LOC_SECTION            ".debug_loc"
+#ifndef DEBUG_LOC_SECTION
+#define DEBUG_LOC_SECTION      ".debug_loc"
+#endif
+#ifndef DEBUG_PUBNAMES_SECTION
+#define DEBUG_PUBNAMES_SECTION ".debug_pubnames"
 #endif
-#ifndef PUBNAMES_SECTION
-#define PUBNAMES_SECTION       ".debug_pubnames"
+#ifndef DEBUG_STR_SECTION
+#define DEBUG_STR_SECTION      ".debug_str"
 #endif
-#ifndef STR_SECTION
-#define STR_SECTION            ".debug_str"
+#ifndef DEBUG_RANGES_SECTION
+#define DEBUG_RANGES_SECTION   ".debug_ranges"
 #endif
 
 /* Standard ELF section names for compiled code and data.  */
-#ifndef TEXT_SECTION
-#define TEXT_SECTION           ".text"
+#ifndef TEXT_SECTION_NAME
+#define TEXT_SECTION_NAME      ".text"
 #endif
-#ifndef DATA_SECTION
-#define DATA_SECTION           ".data"
-#endif
-#ifndef BSS_SECTION
-#define BSS_SECTION            ".bss"
+
+/* Section flags for .debug_str section.  */
+#ifdef HAVE_GAS_SHF_MERGE
+#define DEBUG_STR_SECTION_FLAGS \
+  (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1)
+#else
+#define DEBUG_STR_SECTION_FLAGS        SECTION_DEBUG
 #endif
 
 /* Labels we insert at beginning sections we can reference instead of
    the section names themselves.  */
 
 #ifndef TEXT_SECTION_LABEL
-#define TEXT_SECTION_LABEL      "Ltext"
+#define TEXT_SECTION_LABEL             "Ltext"
 #endif
 #ifndef DEBUG_LINE_SECTION_LABEL
-#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
+#define DEBUG_LINE_SECTION_LABEL       "Ldebug_line"
 #endif
 #ifndef DEBUG_INFO_SECTION_LABEL
-#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
+#define DEBUG_INFO_SECTION_LABEL       "Ldebug_info"
+#endif
+#ifndef DEBUG_ABBREV_SECTION_LABEL
+#define DEBUG_ABBREV_SECTION_LABEL     "Ldebug_abbrev"
 #endif
-#ifndef ABBREV_SECTION_LABEL
-#define ABBREV_SECTION_LABEL     "Ldebug_abbrev"
+#ifndef DEBUG_LOC_SECTION_LABEL
+#define DEBUG_LOC_SECTION_LABEL                "Ldebug_loc"
+#endif
+#ifndef DEBUG_RANGES_SECTION_LABEL
+#define DEBUG_RANGES_SECTION_LABEL     "Ldebug_ranges"
+#endif
+#ifndef DEBUG_MACINFO_SECTION_LABEL
+#define DEBUG_MACINFO_SECTION_LABEL     "Ldebug_macinfo"
 #endif
 
 /* Definitions of defaults for formats and names of various special
@@ -3432,7 +3694,9 @@ static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
+static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 #ifndef TEXT_END_LABEL
 #define TEXT_END_LABEL         "Letext"
 #endif
@@ -3479,7 +3743,7 @@ dwarf2out_set_demangle_name_func (func)
 
 static rtx
 save_rtx (orig)
-     register rtx orig;
+     rtx orig;
 {
   VARRAY_PUSH_RTX (used_rtx_varray, orig);
 
@@ -3490,11 +3754,11 @@ save_rtx (orig)
 
 static inline int
 is_pseudo_reg (rtl)
-     register rtx rtl;
+     rtx rtl;
 {
   return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
          || (GET_CODE (rtl) == SUBREG
-             && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
+             && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER));
 }
 
 /* Return a reference to a type, with its const and volatile qualifiers
@@ -3502,7 +3766,7 @@ is_pseudo_reg (rtl)
 
 static inline tree
 type_main_variant (type)
-     register tree type;
+     tree type;
 {
   type = TYPE_MAIN_VARIANT (type);
 
@@ -3522,9 +3786,9 @@ type_main_variant (type)
 
 static inline int
 is_tagged_type (type)
-     register tree type;
+     tree type;
 {
-  register enum tree_code code = TREE_CODE (type);
+  enum tree_code code = TREE_CODE (type);
 
   return (code == RECORD_TYPE || code == UNION_TYPE
          || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
@@ -3534,7 +3798,7 @@ is_tagged_type (type)
 
 static const char *
 dwarf_tag_name (tag)
-     register unsigned tag;
+     unsigned tag;
 {
   switch (tag)
     {
@@ -3655,7 +3919,7 @@ dwarf_tag_name (tag)
 
 static const char *
 dwarf_attr_name (attr)
-     register unsigned attr;
+     unsigned attr;
 {
   switch (attr)
     {
@@ -3784,6 +4048,31 @@ dwarf_attr_name (attr)
     case DW_AT_vtable_elem_location:
       return "DW_AT_vtable_elem_location";
 
+    case DW_AT_allocated:
+      return "DW_AT_allocated";
+    case DW_AT_associated:
+      return "DW_AT_associated";
+    case DW_AT_data_location:
+      return "DW_AT_data_location";
+    case DW_AT_stride:
+      return "DW_AT_stride";
+    case DW_AT_entry_pc:
+      return "DW_AT_entry_pc";
+    case DW_AT_use_UTF8:
+      return "DW_AT_use_UTF8";
+    case DW_AT_extension:
+      return "DW_AT_extension";
+    case DW_AT_ranges:
+      return "DW_AT_ranges";
+    case DW_AT_trampoline:
+      return "DW_AT_trampoline";
+    case DW_AT_call_column:
+      return "DW_AT_call_column";
+    case DW_AT_call_file:
+      return "DW_AT_call_file";
+    case DW_AT_call_line:
+      return "DW_AT_call_line";
+
     case DW_AT_MIPS_fde:
       return "DW_AT_MIPS_fde";
     case DW_AT_MIPS_loop_begin:
@@ -3819,6 +4108,9 @@ dwarf_attr_name (attr)
       return "DW_AT_body_begin";
     case DW_AT_body_end:
       return "DW_AT_body_end";
+    case DW_AT_VMS_rtnbeg_pd_address:
+      return "DW_AT_VMS_rtnbeg_pd_address";
+
     default:
       return "DW_AT_<unknown>";
     }
@@ -3828,7 +4120,7 @@ dwarf_attr_name (attr)
 
 static const char *
 dwarf_form_name (form)
-     register unsigned form;
+     unsigned form;
 {
   switch (form)
     {
@@ -3884,7 +4176,7 @@ dwarf_form_name (form)
 #if 0
 static const char *
 dwarf_type_encoding_name (enc)
-     register unsigned enc;
+     unsigned enc;
 {
   switch (enc)
     {
@@ -3918,7 +4210,7 @@ dwarf_type_encoding_name (enc)
 
 static tree
 decl_ultimate_origin (decl)
-     register tree decl;
+     tree decl;
 {
   /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the
      nodes in the function to point to themselves; ignore that if
@@ -3944,9 +4236,9 @@ decl_ultimate_origin (decl)
 
 static tree
 block_ultimate_origin (block)
-     register tree block;
+     tree block;
 {
-  register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
+  tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
 
   /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the
      nodes in the function to point to themselves; ignore that if
@@ -3958,8 +4250,8 @@ block_ultimate_origin (block)
     return NULL_TREE;
   else
     {
-      register tree ret_val;
-      register tree lookahead = immediate_origin;
+      tree ret_val;
+      tree lookahead = immediate_origin;
 
       do
        {
@@ -4001,8 +4293,8 @@ decl_class_context (decl)
 
 static inline void
 add_dwarf_attr (die, attr)
-     register dw_die_ref die;
-     register dw_attr_ref attr;
+     dw_die_ref die;
+     dw_attr_ref attr;
 {
   if (die != NULL && attr != NULL)
     {
@@ -4023,11 +4315,11 @@ AT_class (a)
 
 static inline void
 add_AT_flag (die, attr_kind, flag)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register unsigned flag;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned flag;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4039,7 +4331,7 @@ add_AT_flag (die, attr_kind, flag)
 static inline unsigned AT_flag PARAMS ((dw_attr_ref));
 static inline unsigned
 AT_flag (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_flag)
     return a->dw_attr_val.v.val_flag;
@@ -4051,11 +4343,11 @@ AT_flag (a)
 
 static inline void
 add_AT_int (die, attr_kind, int_val)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register long int int_val;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     long int int_val;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4067,7 +4359,7 @@ add_AT_int (die, attr_kind, int_val)
 static inline long int AT_int PARAMS ((dw_attr_ref));
 static inline long int
 AT_int (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_const)
     return a->dw_attr_val.v.val_int;
@@ -4079,11 +4371,11 @@ AT_int (a)
 
 static inline void
 add_AT_unsigned (die, attr_kind, unsigned_val)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register unsigned long unsigned_val;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned long unsigned_val;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4095,7 +4387,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
 static inline unsigned long AT_unsigned PARAMS ((dw_attr_ref));
 static inline unsigned long
 AT_unsigned (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_unsigned_const)
     return a->dw_attr_val.v.val_unsigned;
@@ -4107,12 +4399,12 @@ AT_unsigned (a)
 
 static inline void
 add_AT_long_long (die, attr_kind, val_hi, val_low)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register unsigned long val_hi;
-     register unsigned long val_low;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned long val_hi;
+     unsigned long val_low;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4126,12 +4418,12 @@ add_AT_long_long (die, attr_kind, val_hi, val_low)
 
 static inline void
 add_AT_float (die, attr_kind, length, array)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register unsigned length;
-     register long *array;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned length;
+     long *array;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4145,26 +4437,83 @@ add_AT_float (die, attr_kind, length, array)
 
 static inline void
 add_AT_string (die, attr_kind, str)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register const char *str;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     const char *str;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  struct indirect_string_node *node;
+  
+  if (! debug_str_hash)
+    {
+      debug_str_hash = ht_create (10);
+      debug_str_hash->alloc_node = indirect_string_alloc;
+    }
+
+  node = (struct indirect_string_node *)
+        ht_lookup (debug_str_hash, (const unsigned char *) str,
+                   strlen (str), HT_ALLOC);
+  node->refcount++;
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
   attr->dw_attr_val.val_class = dw_val_class_str;
-  attr->dw_attr_val.v.val_str = xstrdup (str);
+  attr->dw_attr_val.v.val_str = node;
   add_dwarf_attr (die, attr);
 }
 
 static inline const char *AT_string PARAMS ((dw_attr_ref));
 static inline const char *
 AT_string (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
+{
+  if (a && AT_class (a) == dw_val_class_str)
+    return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id);
+
+  abort ();
+}
+
+/* Find out whether a string should be output inline in DIE
+   or out-of-line in .debug_str section.  */
+
+static int AT_string_form PARAMS ((dw_attr_ref));
+static int
+AT_string_form (a)
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_str)
-    return a->dw_attr_val.v.val_str;
+    {
+      struct indirect_string_node *node;
+      unsigned int len;
+      extern int const_labelno;
+      char label[32];
+
+      node = a->dw_attr_val.v.val_str;
+      if (node->form)
+       return node->form;
+
+      len = HT_LEN (&node->id) + 1;
+
+      /* If the string is shorter or equal to the size
+        of the reference, it is always better to put it
+        inline.  */
+      if (len <= DWARF_OFFSET_SIZE || node->refcount == 0)
+       return node->form = DW_FORM_string;
+
+      if ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0)
+       {
+         /* If we cannot expect the linker to merge strings
+            in .debug_str section, only put it into .debug_str
+            if it is worth even in this single module.  */
+         if ((len - DWARF_OFFSET_SIZE) * node->refcount <= len)
+           return node->form = DW_FORM_string;
+       }
+
+      ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
+      ++const_labelno;
+      node->label = xstrdup (label);
+      return node->form = DW_FORM_strp;
+    }
 
   abort ();
 }
@@ -4173,11 +4522,11 @@ AT_string (a)
 
 static inline void
 add_AT_die_ref (die, attr_kind, targ_die)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register dw_die_ref targ_die;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     dw_die_ref targ_die;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4190,7 +4539,7 @@ add_AT_die_ref (die, attr_kind, targ_die)
 static inline dw_die_ref AT_ref PARAMS ((dw_attr_ref));
 static inline dw_die_ref
 AT_ref (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     return a->dw_attr_val.v.val_die_ref.die;
@@ -4201,7 +4550,7 @@ AT_ref (a)
 static inline int AT_ref_external PARAMS ((dw_attr_ref));
 static inline int
 AT_ref_external (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     return a->dw_attr_val.v.val_die_ref.external;
@@ -4212,7 +4561,7 @@ AT_ref_external (a)
 static inline void set_AT_ref_external PARAMS ((dw_attr_ref, int));
 static inline void
 set_AT_ref_external (a, i)
-     register dw_attr_ref a;
+     dw_attr_ref a;
      int i;
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
@@ -4225,11 +4574,11 @@ set_AT_ref_external (a, i)
 
 static inline void
 add_AT_fde_ref (die, attr_kind, targ_fde)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register unsigned targ_fde;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned targ_fde;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4242,11 +4591,11 @@ add_AT_fde_ref (die, attr_kind, targ_fde)
 
 static inline void
 add_AT_loc (die, attr_kind, loc)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register dw_loc_descr_ref loc;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     dw_loc_descr_ref loc;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4258,7 +4607,7 @@ add_AT_loc (die, attr_kind, loc)
 static inline dw_loc_descr_ref AT_loc PARAMS ((dw_attr_ref));
 static inline dw_loc_descr_ref
 AT_loc (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_loc)
     return a->dw_attr_val.v.val_loc;
@@ -4266,27 +4615,55 @@ AT_loc (a)
   abort ();
 }
 
-/* Add an address constant attribute value to a DIE.  */
-
 static inline void
-add_AT_addr (die, attr_kind, addr)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     rtx addr;
+add_AT_loc_list (die, attr_kind, loc_list)
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     dw_loc_list_ref loc_list;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
-  attr->dw_attr_val.val_class = dw_val_class_addr;
-  attr->dw_attr_val.v.val_addr = addr;
+  attr->dw_attr_val.val_class = dw_val_class_loc_list;
+  attr->dw_attr_val.v.val_loc_list = loc_list;
   add_dwarf_attr (die, attr);
+  have_location_lists = 1;
 }
 
-static inline rtx AT_addr PARAMS ((dw_attr_ref));
+static inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref));
+
+static inline dw_loc_list_ref
+AT_loc_list (a)
+     dw_attr_ref a;
+{
+  if (a && AT_class (a) == dw_val_class_loc_list)
+    return a->dw_attr_val.v.val_loc_list;
+
+  abort ();
+}
+
+/* Add an address constant attribute value to a DIE.  */
+
+static inline void
+add_AT_addr (die, attr_kind, addr)
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     rtx addr;
+{
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+  attr->dw_attr_next = NULL;
+  attr->dw_attr = attr_kind;
+  attr->dw_attr_val.val_class = dw_val_class_addr;
+  attr->dw_attr_val.v.val_addr = addr;
+  add_dwarf_attr (die, attr);
+}
+
+static inline rtx AT_addr PARAMS ((dw_attr_ref));
 static inline rtx
 AT_addr (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && AT_class (a) == dw_val_class_addr)
     return a->dw_attr_val.v.val_addr;
@@ -4298,11 +4675,11 @@ AT_addr (a)
 
 static inline void
 add_AT_lbl_id (die, attr_kind, lbl_id)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register const char *lbl_id;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     const char *lbl_id;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4315,11 +4692,11 @@ add_AT_lbl_id (die, attr_kind, lbl_id)
 
 static inline void
 add_AT_lbl_offset (die, attr_kind, label)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
-     register const char *label;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     const char *label;
 {
-  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4328,10 +4705,44 @@ add_AT_lbl_offset (die, attr_kind, label)
   add_dwarf_attr (die, attr);
 }
 
+/* Add an offset attribute value to a DIE.  */
+
+static inline void
+add_AT_offset (die, attr_kind, offset)
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned long offset;
+{
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+  attr->dw_attr_next = NULL;
+  attr->dw_attr = attr_kind;
+  attr->dw_attr_val.val_class = dw_val_class_offset;
+  attr->dw_attr_val.v.val_offset = offset;
+  add_dwarf_attr (die, attr);
+}
+
+/* Add an range_list attribute value to a DIE.  */
+
+static void
+add_AT_range_list (die, attr_kind, offset)
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
+     unsigned long offset;
+{
+  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+  attr->dw_attr_next = NULL;
+  attr->dw_attr = attr_kind;
+  attr->dw_attr_val.val_class = dw_val_class_range_list;
+  attr->dw_attr_val.v.val_offset = offset;
+  add_dwarf_attr (die, attr);
+}
+
 static inline const char *AT_lbl PARAMS ((dw_attr_ref));
 static inline const char *
 AT_lbl (a)
-     register dw_attr_ref a;
+     dw_attr_ref a;
 {
   if (a && (AT_class (a) == dw_val_class_lbl_id
            || AT_class (a) == dw_val_class_lbl_offset))
@@ -4344,11 +4755,11 @@ AT_lbl (a)
 
 static inline dw_attr_ref
 get_AT (die, attr_kind)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
 {
-  register dw_attr_ref a;
-  register dw_die_ref spec = NULL;
+  dw_attr_ref a;
+  dw_die_ref spec = NULL;
 
   if (die != NULL)
     {
@@ -4371,27 +4782,27 @@ get_AT (die, attr_kind)
 
 /* Return the "low pc" attribute value, typically associated with
    a subprogram DIE.  Return null if the "low pc" attribute is
-   either not prsent, or if it cannot be represented as an
+   either not present, or if it cannot be represented as an
    assembler label identifier.  */
 
 static inline const char *
 get_AT_low_pc (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_attr_ref a = get_AT (die, DW_AT_low_pc);
+  dw_attr_ref a = get_AT (die, DW_AT_low_pc);
   return a ? AT_lbl (a) : NULL;
 }
 
 /* Return the "high pc" attribute value, typically associated with
    a subprogram DIE.  Return null if the "high pc" attribute is
-   either not prsent, or if it cannot be represented as an
+   either not present, or if it cannot be represented as an
    assembler label identifier.  */
 
 static inline const char *
 get_AT_hi_pc (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_attr_ref a = get_AT (die, DW_AT_high_pc);
+  dw_attr_ref a = get_AT (die, DW_AT_high_pc);
   return a ? AT_lbl (a) : NULL;
 }
 
@@ -4400,10 +4811,10 @@ get_AT_hi_pc (die)
 
 static inline const char *
 get_AT_string (die, attr_kind)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
 {
-  register dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_ref a = get_AT (die, attr_kind);
   return a ? AT_string (a) : NULL;
 }
 
@@ -4412,10 +4823,10 @@ get_AT_string (die, attr_kind)
 
 static inline int
 get_AT_flag (die, attr_kind)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
 {
-  register dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_ref a = get_AT (die, attr_kind);
   return a ? AT_flag (a) : 0;
 }
 
@@ -4424,35 +4835,42 @@ get_AT_flag (die, attr_kind)
 
 static inline unsigned
 get_AT_unsigned (die, attr_kind)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
 {
-  register dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_ref a = get_AT (die, attr_kind);
   return a ? AT_unsigned (a) : 0;
 }
 
 static inline dw_die_ref
 get_AT_ref (die, attr_kind)
      dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
+     enum dwarf_attribute attr_kind;
 {
-  register dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_ref a = get_AT (die, attr_kind);
   return a ? AT_ref (a) : NULL;
 }
 
 static inline int
 is_c_family ()
 {
-  register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
   return (lang == DW_LANG_C || lang == DW_LANG_C89
          || lang == DW_LANG_C_plus_plus);
 }
 
 static inline int
+is_cxx ()
+{
+  return (get_AT_unsigned (comp_unit_die, DW_AT_language)
+         == DW_LANG_C_plus_plus);
+}  
+
+static inline int
 is_fortran ()
 {
-  register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
   return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90);
 }
@@ -4460,7 +4878,7 @@ is_fortran ()
 static inline int
 is_java ()
 {
-  register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
   return (lang == DW_LANG_Java);
 }
@@ -4475,9 +4893,13 @@ free_AT (a)
   switch (AT_class (a))
     {
     case dw_val_class_str:
+      if (a->dw_attr_val.v.val_str->refcount)
+       a->dw_attr_val.v.val_str->refcount--;
+      break;
+
     case dw_val_class_lbl_id:
     case dw_val_class_lbl_offset:
-      free (a->dw_attr_val.v.val_str);
+      free (a->dw_attr_val.v.val_lbl_id);
       break;
 
     case dw_val_class_float:
@@ -4495,11 +4917,11 @@ free_AT (a)
 
 static void
 remove_AT (die, attr_kind)
-     register dw_die_ref die;
-     register enum dwarf_attribute attr_kind;
+     dw_die_ref die;
+     enum dwarf_attribute attr_kind;
 {
-  register dw_attr_ref *p;
-  register dw_attr_ref removed = NULL;
+  dw_attr_ref *p;
+  dw_attr_ref removed = NULL;
 
   if (die != NULL)
     {
@@ -4531,22 +4953,22 @@ free_die (die)
 
 static void
 remove_children (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_die_ref child_die = die->die_child;
+  dw_die_ref child_die = die->die_child;
 
   die->die_child = NULL;
 
   while (child_die != NULL)
     {
-      register dw_die_ref tmp_die = child_die;
-      register dw_attr_ref a;
+      dw_die_ref tmp_die = child_die;
+      dw_attr_ref a;
 
       child_die = child_die->die_sib;
 
       for (a = tmp_die->die_attr; a != NULL;)
        {
-         register dw_attr_ref tmp_a = a;
+         dw_attr_ref tmp_a = a;
 
          a = a->dw_attr_next;
          free_AT (tmp_a);
@@ -4561,8 +4983,8 @@ remove_children (die)
 
 static inline void
 add_child_die (die, child_die)
-     register dw_die_ref die;
-     register dw_die_ref child_die;
+     dw_die_ref die;
+     dw_die_ref child_die;
 {
   if (die != NULL && child_die != NULL)
     {
@@ -4611,10 +5033,10 @@ splice_child_die (parent, child)
 
 static inline dw_die_ref
 new_die (tag_value, parent_die)
-     register enum dwarf_tag tag_value;
-     register dw_die_ref parent_die;
+     enum dwarf_tag tag_value;
+     dw_die_ref parent_die;
 {
-  register dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
+  dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
 
   die->die_tag = tag_value;
 
@@ -4637,7 +5059,7 @@ new_die (tag_value, parent_die)
 
 static inline dw_die_ref
 lookup_type_die (type)
-     register tree type;
+     tree type;
 {
   if (TREE_CODE (type) == VECTOR_TYPE)
     type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
@@ -4648,8 +5070,8 @@ lookup_type_die (type)
 
 static inline void
 equate_type_number_to_die (type, type_die)
-     register tree type;
-     register dw_die_ref type_die;
+     tree type;
+     dw_die_ref type_die;
 {
   TYPE_SYMTAB_POINTER (type) = (char *) type_die;
 }
@@ -4658,9 +5080,9 @@ equate_type_number_to_die (type, type_die)
 
 static inline dw_die_ref
 lookup_decl_die (decl)
-     register tree decl;
+     tree decl;
 {
-  register unsigned decl_id = DECL_UID (decl);
+  unsigned decl_id = DECL_UID (decl);
 
   return (decl_id < decl_die_table_in_use
          ? decl_die_table[decl_id] : NULL);
@@ -4670,11 +5092,11 @@ lookup_decl_die (decl)
 
 static void
 equate_decl_number_to_die (decl, decl_die)
-     register tree decl;
-     register dw_die_ref decl_die;
+     tree decl;
+     dw_die_ref decl_die;
 {
-  register unsigned decl_id = DECL_UID (decl);
-  register unsigned num_allocated;
+  unsigned decl_id = DECL_UID (decl);
+  unsigned num_allocated;
 
   if (decl_id >= decl_die_table_allocated)
     {
@@ -4720,8 +5142,8 @@ print_die (die, outfile)
      dw_die_ref die;
      FILE *outfile;
 {
-  register dw_attr_ref a;
-  register dw_die_ref c;
+  dw_attr_ref a;
+  dw_die_ref c;
 
   print_spaces (outfile);
   fprintf (outfile, "DIE %4lu: %s\n",
@@ -4740,9 +5162,19 @@ print_die (die, outfile)
        case dw_val_class_addr:
          fprintf (outfile, "address");
          break;
+       case dw_val_class_offset:
+         fprintf (outfile, "offset");
+         break;
        case dw_val_class_loc:
          fprintf (outfile, "location descriptor");
          break;
+       case dw_val_class_loc_list:
+         fprintf (outfile, "location list -> label:%s",
+                  AT_loc_list (a)->ll_symbol);
+         break;
+       case dw_val_class_range_list:
+         fprintf (outfile, "range list");
+         break;
        case dw_val_class_const:
          fprintf (outfile, "%ld", AT_int (a));
          break;
@@ -4807,8 +5239,8 @@ static void
 print_dwarf_line_table (outfile)
      FILE *outfile;
 {
-  register unsigned i;
-  register dw_line_info_ref line_info;
+  unsigned i;
+  dw_line_info_ref line_info;
 
   fprintf (outfile, "\n\nDWARF source line information\n");
   for (i = 1; i < line_info_table_in_use; ++i)
@@ -4850,10 +5282,10 @@ debug_dwarf ()
 
 static void
 reverse_die_lists (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_die_ref c, cp, cn;
-  register dw_attr_ref a, ap, an;
+  dw_die_ref c, cp, cn;
+  dw_attr_ref a, ap, an;
 
   for (a = die->die_attr, ap = 0; a; a = an)
     {
@@ -4881,9 +5313,9 @@ reverse_die_lists (die)
 
 static void
 reverse_all_dies (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_die_ref c;
+  dw_die_ref c;
 
   reverse_die_lists (die);
 
@@ -4972,6 +5404,7 @@ attr_checksum (at, ctx)
     case dw_val_class_str:
       PROCESS_STRING (AT_string (at));
       break;
+
     case dw_val_class_addr:
       r = AT_addr (at);
       switch (GET_CODE (r))
@@ -4985,6 +5418,10 @@ attr_checksum (at, ctx)
        }
       break;
 
+    case dw_val_class_offset:
+      PROCESS (at->dw_attr_val.v.val_offset);
+      break;
+
     case dw_val_class_loc:
       for (loc = AT_loc (at); loc; loc = loc->dw_loc_next)
        loc_checksum (loc, ctx);
@@ -4998,6 +5435,7 @@ attr_checksum (at, ctx)
     case dw_val_class_fde_ref:
     case dw_val_class_lbl_id:
     case dw_val_class_lbl_offset:
+      break;
 
     default:
       break;
@@ -5040,7 +5478,7 @@ static void
 compute_section_prefix (unit_die)
      dw_die_ref unit_die;
 {
-  char *p, *name;
+  char *name;
   int i;
   unsigned char checksum[16];
   struct md5_ctx ctx;
@@ -5049,18 +5487,22 @@ compute_section_prefix (unit_die)
   die_checksum (unit_die, &ctx);
   md5_finish_ctx (&ctx, checksum);
 
-  p = lbasename (get_AT_string (unit_die, DW_AT_name));
-  name = (char *) alloca (strlen (p) + 64);
-  sprintf (name, "%s.", p);
+  {
+    const char *p = lbasename (get_AT_string (unit_die, DW_AT_name));
+    name = (char *) alloca (strlen (p) + 64);
+    sprintf (name, "%s.", p);
+  }
 
   clean_symbol_name (name);
 
-  p = name + strlen (name);
-  for (i = 0; i < 4; ++i)
-    {
-      sprintf (p, "%.2x", checksum[i]);
-      p += 2;
-    }
+  {
+    char *p = name + strlen (name);
+    for (i = 0; i < 4; ++i)
+      {
+       sprintf (p, "%.2x", checksum[i]);
+       p += 2;
+      }
+  }
 
   comdat_symbol_id = unit_die->die_symbol = xstrdup (name);
   comdat_symbol_number = 0;
@@ -5137,18 +5579,19 @@ is_symbol_die (c)
 {
   if (is_type_die (c))
     return 1;
-  if (get_AT (c, DW_AT_declaration)
+  if (get_AT (c, DW_AT_declaration) 
       && ! get_AT (c, DW_AT_specification))
     return 1;
   return 0;
 }
 
 static char *
-gen_internal_sym ()
+gen_internal_sym (prefix)
+       const char *prefix;
 {
   char buf[256];
   static int label_num;
-  ASM_GENERATE_INTERNAL_LABEL (buf, "LDIE", label_num++);
+  ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++);
   return xstrdup (buf);
 }
 
@@ -5156,9 +5599,9 @@ gen_internal_sym ()
 
 static void
 assign_symbol_names (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_die_ref c;
+  dw_die_ref c;
 
   if (is_symbol_die (die))
     {
@@ -5170,7 +5613,7 @@ assign_symbol_names (die)
          die->die_symbol = xstrdup (p);
        }
       else
-       die->die_symbol = gen_internal_sym ();
+       die->die_symbol = gen_internal_sym ("LDIE");
     }
 
   for (c = die->die_child; c != NULL; c = c->die_sib)
@@ -5183,15 +5626,15 @@ assign_symbol_names (die)
 
 static void
 break_out_includes (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
   dw_die_ref *ptr;
-  register dw_die_ref unit = NULL;
+  dw_die_ref unit = NULL;
   limbo_die_node *node;
 
   for (ptr = &(die->die_child); *ptr; )
     {
-      register dw_die_ref c = *ptr;
+      dw_die_ref c = *ptr;
 
       if (c->die_tag == DW_TAG_GNU_BINCL
          || c->die_tag == DW_TAG_GNU_EINCL
@@ -5242,9 +5685,9 @@ break_out_includes (die)
 
 static void
 add_sibling_attributes (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_die_ref c;
+  dw_die_ref c;
 
   if (die->die_tag != DW_TAG_compile_unit
       && die->die_sib && die->die_child != NULL)
@@ -5255,6 +5698,24 @@ add_sibling_attributes (die)
     add_sibling_attributes (c);
 }
 
+/* Output all location lists for the DIE and it's children */
+static void
+output_location_lists (die)
+     dw_die_ref die;
+{
+  dw_die_ref c;
+  dw_attr_ref d_attr;
+  for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next)
+    {
+      if (AT_class (d_attr) == dw_val_class_loc_list)
+       {
+         output_loc_list (AT_loc_list (d_attr));
+       }
+    }
+  for (c = die->die_child; c != NULL; c = c->die_sib)
+    output_location_lists (c);
+
+}
 /* The format of each DIE (and its attribute value pairs)
    is encoded in an abbreviation table.  This routine builds the
    abbreviation table and assigns a unique abbreviation id for
@@ -5263,12 +5724,12 @@ add_sibling_attributes (die)
 
 static void
 build_abbrev_table (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register unsigned long abbrev_id;
-  register unsigned long n_alloc;
-  register dw_die_ref c;
-  register dw_attr_ref d_attr, a_attr;
+  unsigned long abbrev_id;
+  unsigned int n_alloc;
+  dw_die_ref c;
+  dw_attr_ref d_attr, a_attr;
 
   /* Scan the DIE references, and mark as external any that refer to
      DIEs from other CUs (i.e. those which are not marked).  */
@@ -5285,7 +5746,7 @@ build_abbrev_table (die)
 
   for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
     {
-      register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
+      dw_die_ref abbrev = abbrev_die_table[abbrev_id];
 
       if (abbrev->die_tag == die->die_tag)
        {
@@ -5333,20 +5794,6 @@ build_abbrev_table (die)
     build_abbrev_table (c);
 }
 \f
-/* Return the size of a string, including the null byte.
-
-   This used to treat backslashes as escapes, and hence they were not included
-   in the count.  However, that conflicts with what ASM_OUTPUT_ASCII does,
-   which treats a backslash as a backslash, escaping it if necessary, and hence
-   we must include them in the count.  */
-
-static unsigned long
-size_of_string (str)
-     register const char *str;
-{
-  return strlen (str) + 1;
-}
-
 /* Return the power-of-two number of bytes necessary to represent VALUE.  */
 
 static int
@@ -5371,10 +5818,10 @@ constant_size (value)
 
 static unsigned long
 size_of_die (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register unsigned long size = 0;
-  register dw_attr_ref a;
+  unsigned long size = 0;
+  dw_attr_ref a;
 
   size += size_of_uleb128 (die->die_abbrev);
   for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
@@ -5384,15 +5831,24 @@ size_of_die (die)
        case dw_val_class_addr:
          size += DWARF2_ADDR_SIZE;
          break;
+       case dw_val_class_offset:
+         size += DWARF_OFFSET_SIZE;
+         break;
        case dw_val_class_loc:
          {
-           register unsigned long lsize = size_of_locs (AT_loc (a));
+           unsigned long lsize = size_of_locs (AT_loc (a));
 
            /* Block length.  */
            size += constant_size (lsize);
            size += lsize;
          }
          break;
+       case dw_val_class_loc_list:
+         size += DWARF_OFFSET_SIZE;
+         break;
+       case dw_val_class_range_list:
+         size += DWARF_OFFSET_SIZE;
+         break;
        case dw_val_class_const:
          size += size_of_sleb128 (AT_int (a));
          break;
@@ -5421,7 +5877,10 @@ size_of_die (die)
          size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_str:
-         size += size_of_string (AT_string (a));
+         if (AT_string_form (a) == DW_FORM_strp)
+           size += DWARF_OFFSET_SIZE;
+         else
+           size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1;
          break;
        default:
          abort ();
@@ -5441,7 +5900,7 @@ static void
 calc_die_sizes (die)
      dw_die_ref die;
 {
-  register dw_die_ref c;
+  dw_die_ref c;
   die->die_offset = next_die_offset;
   next_die_offset += size_of_die (die);
 
@@ -5462,7 +5921,7 @@ static void
 mark_dies (die)
      dw_die_ref die;
 {
-  register dw_die_ref c;
+  dw_die_ref c;
   die->die_mark = 1;
   for (c = die->die_child; c; c = c->die_sib)
     mark_dies (c);
@@ -5474,7 +5933,7 @@ static void
 unmark_dies (die)
      dw_die_ref die;
 {
-  register dw_die_ref c;
+  dw_die_ref c;
   die->die_mark = 0;
   for (c = die->die_child; c; c = c->die_sib)
     unmark_dies (c);
@@ -5486,14 +5945,14 @@ unmark_dies (die)
 static unsigned long
 size_of_pubnames ()
 {
-  register unsigned long size;
-  register unsigned i;
+  unsigned long size;
+  unsigned i;
 
   size = DWARF_PUBNAMES_HEADER_SIZE;
   for (i = 0; i < pubname_table_in_use; ++i)
     {
-      register pubname_ref p = &pubname_table[i];
-      size += DWARF_OFFSET_SIZE + size_of_string (p->name);
+      pubname_ref p = &pubname_table[i];
+      size += DWARF_OFFSET_SIZE + strlen (p->name) + 1;
     }
 
   size += DWARF_OFFSET_SIZE;
@@ -5505,7 +5964,7 @@ size_of_pubnames ()
 static unsigned long
 size_of_aranges ()
 {
-  register unsigned long size;
+  unsigned long size;
 
   size = DWARF_ARANGES_HEADER_SIZE;
 
@@ -5528,6 +5987,17 @@ value_format (a)
     {
     case dw_val_class_addr:
       return DW_FORM_addr;
+    case dw_val_class_range_list:
+    case dw_val_class_offset:
+      if (DWARF_OFFSET_SIZE == 4)
+       return DW_FORM_data4;
+      if (DWARF_OFFSET_SIZE == 8)
+       return DW_FORM_data8;
+      abort ();
+    case dw_val_class_loc_list:
+      /* FIXME: Could be DW_FORM_data8, with a > 32 bit size
+        .debug_loc section */
+      return DW_FORM_data4;
     case dw_val_class_loc:
       switch (constant_size (size_of_locs (AT_loc (a))))
        {
@@ -5572,7 +6042,8 @@ value_format (a)
     case dw_val_class_lbl_offset:
       return DW_FORM_data;
     case dw_val_class_str:
-      return DW_FORM_string;
+      return AT_string_form (a);
+
     default:
       abort ();
     }
@@ -5599,7 +6070,7 @@ output_abbrev_section ()
   dw_attr_ref a_attr;
   for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
     {
-      register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
+      dw_die_ref abbrev = abbrev_die_table[abbrev_id];
 
       dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)");
 
@@ -5631,7 +6102,7 @@ output_abbrev_section ()
 
 static inline void
 output_die_symbol (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
   char *sym = die->die_symbol;
 
@@ -5646,16 +6117,102 @@ output_die_symbol (die)
   ASM_OUTPUT_LABEL (asm_out_file, sym);
 }
 
+/* Return a new location list, given the begin and end range, and the
+   expression. gensym tells us whether to generate a new internal
+   symbol for this location list node, which is done for the head of
+   the list only.  */ 
+static inline dw_loc_list_ref
+new_loc_list (expr, begin, end, section, gensym)
+     dw_loc_descr_ref expr;
+     const char *begin;
+     const char *end;
+     const char *section;
+     unsigned gensym;
+{
+  dw_loc_list_ref retlist
+    = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node));
+  retlist->begin = begin;
+  retlist->end = end;
+  retlist->expr = expr;
+  retlist->section = section;
+  if (gensym) 
+    retlist->ll_symbol = gen_internal_sym ("LLST");
+  return retlist;
+}
+
+/* Add a location description expression to a location list */
+static inline void
+add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
+     dw_loc_list_ref *list_head;
+     dw_loc_descr_ref descr;
+     const char *begin;
+     const char *end;
+     const char *section;
+{
+  dw_loc_list_ref *d;
+  
+  /* Find the end of the chain.  */
+  for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
+    ;
+  /* Add a new location list node to the list */
+  *d = new_loc_list (descr, begin, end, section, 0);
+}
+
+/* Output the location list given to us */
+static void
+output_loc_list (list_head)
+     dw_loc_list_ref list_head;
+{
+  dw_loc_list_ref curr=list_head;
+  ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
+
+  /* ??? This shouldn't be needed now that we've forced the
+     compilation unit base address to zero when there is code
+     in more than one section.  */
+  if (strcmp (curr->section, ".text") == 0)
+    {
+      /* dw2_asm_output_data will mask off any extra bits in the ~0.  */
+      dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT)0,
+                          "Location list base address specifier fake entry");
+      dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section,
+                            "Location list base address specifier base");
+    }
+  for (curr = list_head; curr != NULL; curr=curr->dw_loc_next)
+    {
+      unsigned long size;
+      dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
+                           "Location list begin address (%s)",
+                           list_head->ll_symbol);
+      dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section,
+                           "Location list end address (%s)",
+                           list_head->ll_symbol);
+      size = size_of_locs (curr->expr);
+      
+      /* Output the block length for this list of location operations.  */
+      if (size > 0xffff)
+       abort ();
+      dw2_asm_output_data (2, size, "%s", "Location expression size");
+
+      output_loc_sequence (curr->expr);
+    }
+  dw2_asm_output_data (DWARF_OFFSET_SIZE, 0,
+                      "Location list terminator begin (%s)",
+                      list_head->ll_symbol);
+  dw2_asm_output_data (DWARF_OFFSET_SIZE, 0,
+                      "Location list terminator end (%s)",
+                      list_head->ll_symbol);
+}
+
 /* Output the DIE and its attributes.  Called recursively to generate
    the definitions of each child DIE.  */
 
 static void
 output_die (die)
-     register dw_die_ref die;
+     dw_die_ref die;
 {
-  register dw_attr_ref a;
-  register dw_die_ref c;
-  register unsigned long size;
+  dw_attr_ref a;
+  dw_die_ref c;
+  unsigned long size;
 
   /* If someone in another CU might refer to us, set up a symbol for
      them to point to.  */
@@ -5675,6 +6232,22 @@ output_die (die)
          dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
          break;
 
+       case dw_val_class_offset:
+         dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+                              "%s", name);
+         break;
+
+       case dw_val_class_range_list:
+         {
+           char *p = strchr (ranges_section_label, '\0');
+
+           sprintf (p, "+0x%lx", a->dw_attr_val.v.val_offset);
+           dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
+                                  "%s", name);
+           *p = '\0';
+         }
+         break;
+
        case dw_val_class_loc:
          size = size_of_locs (AT_loc (a));
 
@@ -5722,7 +6295,7 @@ output_die (die)
 
        case dw_val_class_float:
          {
-           register unsigned int i;
+           unsigned int i;
 
            dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4,
                                 "%s", name);
@@ -5737,6 +6310,16 @@ output_die (die)
          dw2_asm_output_data (1, AT_flag (a), "%s", name);
          break;
 
+        case dw_val_class_loc_list:
+         {
+           char *sym = AT_loc_list (a)->ll_symbol;
+           if (sym == 0)
+             abort();
+           dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym,
+                                 loc_section_label, "%s", name);
+         }
+         break;
+
        case dw_val_class_die_ref:
          if (AT_ref_external (a))
            {
@@ -5770,7 +6353,12 @@ output_die (die)
          break;
 
        case dw_val_class_str:
-         dw2_asm_output_nstring (AT_string (a), -1, "%s", name);
+         if (AT_string_form (a) == DW_FORM_strp)
+           dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+                                  a->dw_attr_val.v.val_str->label,
+                                  "%s: \"%s\"", name, AT_string (a));
+         else
+           dw2_asm_output_nstring (AT_string (a), -1, "%s", name);
          break;
 
        default:
@@ -5814,15 +6402,18 @@ output_comp_unit (die)
 {
   const char *secname;
 
-  if (die->die_child == 0)
-    return;
-
-  /* Mark all the DIEs in this CU so we know which get local refs.  */
+  /* Even if there are no children of this DIE, we must output the
+     information about the compilation unit.  Otherwise, on an empty
+     translation unit, we will generate a present, but empty,
+     .debug_info section.  IRIX 6.5 `nm' will then complain when
+     examining the file.
+     
+     Mark all the DIEs in this CU so we know which get local refs.  */
   mark_dies (die);
 
   build_abbrev_table (die);
 
-  /* Initialize the beginning DIE offset - and calculate sizes/offsets.   */
+  /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
   calc_die_sizes (die);
 
@@ -5837,7 +6428,7 @@ output_comp_unit (die)
     secname = (const char *) DEBUG_INFO_SECTION;
 
   /* Output debugging information.  */
-  ASM_OUTPUT_SECTION (asm_out_file, secname);
+  named_section_flags (secname, SECTION_DEBUG);
   output_compilation_unit_header ();
   output_die (die);
 
@@ -5891,8 +6482,8 @@ add_pubname (decl, die)
 static void
 output_pubnames ()
 {
-  register unsigned i;
-  register unsigned long pubnames_length = size_of_pubnames ();
+  unsigned i;
+  unsigned long pubnames_length = size_of_pubnames ();
 
   dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
                       "Length of Public Names Info");
@@ -5907,7 +6498,7 @@ output_pubnames ()
 
   for (i = 0; i < pubname_table_in_use; ++i)
     {
-      register pubname_ref pub = &pubname_table[i];
+      pubname_ref pub = &pubname_table[i];
 
       /* We shouldn't see pubnames for DIEs outside of the main CU.  */
       if (pub->die->die_mark == 0)
@@ -5935,9 +6526,8 @@ add_arange (decl, die)
   if (arange_table_in_use == arange_table_allocated)
     {
       arange_table_allocated += ARANGE_TABLE_INCREMENT;
-      arange_table
-       = (arange_ref) xrealloc (arange_table,
-                                arange_table_allocated * sizeof (dw_die_ref));
+      arange_table = (dw_die_ref *)
+       xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref));
     }
 
   arange_table[arange_table_in_use++] = die;
@@ -5950,8 +6540,8 @@ add_arange (decl, die)
 static void
 output_aranges ()
 {
-  register unsigned i;
-  register unsigned long aranges_length = size_of_aranges ();
+  unsigned i;
+  unsigned long aranges_length = size_of_aranges ();
 
   dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
                       "Length of Address Ranges Info");
@@ -6023,6 +6613,80 @@ output_aranges ()
   dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
 }
 
+/* Add a new entry to .debug_ranges.  Return the offset at which it
+   was placed.  */
+
+static unsigned int
+add_ranges (block)
+     tree block;
+{
+  unsigned int in_use = ranges_table_in_use;
+
+  if (in_use == ranges_table_allocated)
+    {
+      ranges_table_allocated += RANGES_TABLE_INCREMENT;
+      ranges_table = (dw_ranges_ref)
+       xrealloc (ranges_table, (ranges_table_allocated
+                                * sizeof (struct dw_ranges_struct)));
+    }
+
+  ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0);
+  ranges_table_in_use = in_use + 1;
+
+  return in_use * 2 * DWARF2_ADDR_SIZE;
+}
+
+static void
+output_ranges ()
+{
+  unsigned i;
+  static const char *const start_fmt = "Offset 0x%x";
+  const char *fmt = start_fmt;
+
+  for (i = 0; i < ranges_table_in_use; ++i)
+    {
+      int block_num = ranges_table[i].block_num;
+
+      if (block_num)
+       {
+         char blabel[MAX_ARTIFICIAL_LABEL_BYTES];
+         char elabel[MAX_ARTIFICIAL_LABEL_BYTES];
+
+         ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num);
+         ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num);
+
+         /* If all code is in the text section, then the compilation
+            unit base address defaults to DW_AT_low_pc, which is the
+            base of the text section.  */
+         if (separate_line_info_table_in_use == 0)
+           {
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel,
+                                   text_section_label,
+                                   fmt, i * 2 * DWARF2_ADDR_SIZE);
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel,
+                                   text_section_label, NULL);
+           }
+         /* Otherwise, we add a DW_AT_entry_pc attribute to force the
+            compilation unit base address to zero, which allows us to
+            use absolute addresses, and not worry about whether the
+            target supports cross-section arithmetic.  */
+         else
+           {
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+                                  fmt, i * 2 * DWARF2_ADDR_SIZE);
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel, NULL);
+           }
+
+         fmt = NULL;
+       }
+      else
+       {
+         dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
+         dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
+         fmt = start_fmt;
+       }
+    }
+}
 
 /* Data structure containing information about input files.  */
 struct file_info
@@ -6048,6 +6712,7 @@ struct dir_info
 
 /* Callback function for file_info comparison.  We sort by looking at
    the directories in the path.  */
+
 static int
 file_info_cmp (p1, p2)
      const void *p1;
@@ -6058,11 +6723,13 @@ file_info_cmp (p1, p2)
   unsigned char *cp1;
   unsigned char *cp2;
 
-  /* Take care of file names without directories.  */
-  if (s1->path == s1->fname)
-    return -1;
-  else if (s2->path == s2->fname)
-    return 1;
+  /* Take care of file names without directories.  We need to make sure that
+     we return consistent values to qsort since some will get confused if
+     we return the same value when identical operands are passed in opposite
+     orders.  So if neither has a directory, return 0 and otherwise return
+     1 or -1 depending on which one has the directory.  */
+  if ((s1->path == s1->fname || s2->path == s2->fname))
+    return (s2->path == s2->fname) - (s1->path == s1->fname);
 
   cp1 = (unsigned char *) s1->path;
   cp2 = (unsigned char *) s2->path;
@@ -6071,17 +6738,14 @@ file_info_cmp (p1, p2)
     {
       ++cp1;
       ++cp2;
-      /* Reached the end of the first path?  */
-      if (cp1 == (unsigned char *) s1->fname)
-       /* It doesn't really matter in which order files from the
-          same directory are sorted in.  Therefore don't test for
-          the second path reaching the end.  */
-       return -1;
-      else if (cp2 == (unsigned char *) s2->fname)
-       return 1;
+      /* Reached the end of the first path?  If so, handle like above.  */
+      if ((cp1 == (unsigned char *) s1->fname)
+         || (cp2 == (unsigned char *) s2->fname))
+       return ((cp2 == (unsigned char *) s2->fname)
+               - (cp1 == (unsigned char *) s1->fname));
 
       /* Character of current path component the same?  */
-      if (*cp1 != *cp2)
+      else if (*cp1 != *cp2)
        return *cp1 - *cp2;
     }
 }
@@ -6302,14 +6966,14 @@ output_line_info ()
   char l1[20], l2[20], p1[20], p2[20];
   char line_label[MAX_ARTIFICIAL_LABEL_BYTES];
   char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES];
-  register unsigned opc;
-  register unsigned n_op_args;
-  register unsigned long lt_index;
-  register unsigned long current_line;
-  register long line_offset;
-  register long line_delta;
-  register unsigned long current_file;
-  register unsigned long function;
+  unsigned opc;
+  unsigned n_op_args;
+  unsigned long lt_index;
+  unsigned long current_line;
+  long line_offset;
+  long line_delta;
+  unsigned long current_file;
+  unsigned long function;
 
   ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0);
@@ -6375,7 +7039,7 @@ output_line_info ()
   strcpy (prev_line_label, text_section_label);
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
-      register dw_line_info_ref line_info = &line_info_table[lt_index];
+      dw_line_info_ref line_info = &line_info_table[lt_index];
 
 #if 0
       /* Disable this optimization for now; GDB wants to see two line notes
@@ -6484,7 +7148,7 @@ output_line_info ()
   current_line = 1;
   for (lt_index = 0; lt_index < separate_line_info_table_in_use;)
     {
-      register dw_separate_line_info_ref line_info
+      dw_separate_line_info_ref line_info
        = &separate_line_info_table[lt_index];
 
 #if 0
@@ -6607,12 +7271,12 @@ output_line_info ()
 
 static dw_die_ref
 base_type_die (type)
-     register tree type;
+     tree type;
 {
-  register dw_die_ref base_type_result;
-  register const char *type_name;
-  register enum dwarf_type encoding;
-  register tree name = TYPE_NAME (type);
+  dw_die_ref base_type_result;
+  const char *type_name;
+  enum dwarf_type encoding;
+  tree name = TYPE_NAME (type);
 
   if (TREE_CODE (type) == ERROR_MARK
       || TREE_CODE (type) == VOID_TYPE)
@@ -6701,7 +7365,7 @@ base_type_die (type)
 
 static tree
 root_type (type)
-     register tree type;
+     tree type;
 {
   if (TREE_CODE (type) == ERROR_MARK)
     return error_mark_node;
@@ -6725,7 +7389,7 @@ root_type (type)
 
 static inline int
 is_base_type (type)
-     register tree type;
+     tree type;
 {
   switch (TREE_CODE (type))
     {
@@ -6766,34 +7430,47 @@ is_base_type (type)
 
 static dw_die_ref
 modified_type_die (type, is_const_type, is_volatile_type, context_die)
-     register tree type;
-     register int is_const_type;
-     register int is_volatile_type;
-     register dw_die_ref context_die;
+     tree type;
+     int is_const_type;
+     int is_volatile_type;
+     dw_die_ref context_die;
 {
-  register enum tree_code code = TREE_CODE (type);
-  register dw_die_ref mod_type_die = NULL;
-  register dw_die_ref sub_die = NULL;
-  register tree item_type = NULL;
+  enum tree_code code = TREE_CODE (type);
+  dw_die_ref mod_type_die = NULL;
+  dw_die_ref sub_die = NULL;
+  tree item_type = NULL;
 
   if (code != ERROR_MARK)
     {
-      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;
+      tree qualified_type;
+
+      /* See if we already have the appropriately qualified variant of
+        this type.  */
+      qualified_type 
+       = get_qualified_type (type,
+                             ((is_const_type ? TYPE_QUAL_CONST : 0)
+                              | (is_volatile_type 
+                                 ? TYPE_QUAL_VOLATILE : 0)));
+      /* If we do, then we can just use its DIE, if it exists.  */
+      if (qualified_type)
+       {
+         mod_type_die = lookup_type_die (qualified_type);
+         if (mod_type_die)
+           return mod_type_die;
+       }
 
       /* Handle C typedef types.  */
-      if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-         && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+      if (qualified_type && TYPE_NAME (qualified_type) 
+         && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
+         && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
        {
-         tree dtype = TREE_TYPE (TYPE_NAME (type));
-         if (type == dtype)
+         tree type_name = TYPE_NAME (qualified_type);
+         tree dtype = TREE_TYPE (type_name);
+         if (qualified_type == dtype)
            {
              /* For a named type, use the typedef.  */
-             gen_type_die (type, context_die);
-             mod_type_die = lookup_type_die (type);
+             gen_type_die (qualified_type, context_die);
+             mod_type_die = lookup_type_die (qualified_type);
            }
 
          else if (is_const_type < TYPE_READONLY (dtype)
@@ -6801,7 +7478,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
            /* 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)),
+             = modified_type_die (DECL_ORIGINAL_TYPE (type_name),
                                   is_const_type, is_volatile_type,
                                   context_die);
          /* Else cv-qualified version of named type; fall through.  */
@@ -6854,6 +7531,10 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
          if (mod_type_die == NULL)
            abort ();
        }
+
+      /* We want to equate the qualified type to the die below.  */
+      if (qualified_type)
+       type = qualified_type;
     }
 
   equate_type_number_to_die (type, mod_type_die);
@@ -6874,11 +7555,11 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
 }
 
 /* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
-   an enumerated type.   */
+   an enumerated type.  */
 
 static inline int
 type_is_enum (type)
-     register tree type;
+     tree type;
 {
   return TREE_CODE (type) == ENUMERAL_TYPE;
 }
@@ -6887,29 +7568,30 @@ type_is_enum (type)
 
 static unsigned int
 reg_number (rtl)
-     register rtx rtl;
+     rtx rtl;
 {
-  register unsigned regno = REGNO (rtl);
+  unsigned regno = REGNO (rtl);
 
   if (regno >= FIRST_PSEUDO_REGISTER)
-    {
-      warning ("internal regno botch: regno = %d\n", regno);
-      regno = 0;
-    }
+    abort ();
 
-  regno = DBX_REGISTER_NUMBER (regno);
-  return regno;
+  return DBX_REGISTER_NUMBER (regno);
 }
 
-/* Return a location descriptor that designates a machine register.  */
+/* Return a location descriptor that designates a machine register or
+   zero if there is no such.  */
 
 static dw_loc_descr_ref
 reg_loc_descriptor (rtl)
-     register rtx rtl;
+     rtx rtl;
 {
-  register dw_loc_descr_ref loc_result = NULL;
-  register unsigned reg = reg_number (rtl);
+  dw_loc_descr_ref loc_result = NULL;
+  unsigned reg;
+
+  if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
+    return 0;
 
+  reg = reg_number (rtl);
   if (reg <= 31)
     loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0);
   else
@@ -6965,13 +7647,13 @@ based_loc_descr (reg, offset)
      unsigned reg;
      long int offset;
 {
-  register dw_loc_descr_ref loc_result;
+  dw_loc_descr_ref loc_result;
   /* For the "frame base", we use the frame pointer or stack pointer
      registers, since the RTL for local variables is relative to one of
      them.  */
-  register unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed
-                                                 ? HARD_FRAME_POINTER_REGNUM
-                                                 : STACK_POINTER_REGNUM);
+  unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed
+                                        ? HARD_FRAME_POINTER_REGNUM
+                                        : STACK_POINTER_REGNUM);
 
   if (reg == fp_reg)
     loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
@@ -6987,10 +7669,11 @@ based_loc_descr (reg, offset)
 
 static inline int
 is_based_loc (rtl)
-     register rtx rtl;
+     rtx rtl;
 {
     return (GET_CODE (rtl) == PLUS
            && ((GET_CODE (XEXP (rtl, 0)) == REG
+                && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
                 && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
 }
 
@@ -7005,14 +7688,17 @@ is_based_loc (rtl)
    it into Dwarf postfix code as it goes.
 
    MODE is the mode of the memory reference, needed to handle some
-   autoincrement addressing modes.  */
+   autoincrement addressing modes.
+
+   Return 0 if we can't represent the location.  */
 
 static dw_loc_descr_ref
 mem_loc_descriptor (rtl, mode)
-     register rtx rtl;
+     rtx rtl;
      enum machine_mode mode;
 {
   dw_loc_descr_ref mem_loc_result = NULL;
+
   /* Note that for a dynamically sized array, the location we will generate a
      description of here will be the lowest numbered location which is
      actually within the array.  That's *not* necessarily the same as the
@@ -7038,7 +7724,7 @@ mem_loc_descriptor (rtl, mode)
          up an entire register.  For now, just assume that it is
          legitimate to make the Dwarf info refer to the whole register which
          contains the given subreg.  */
-      rtl = XEXP (rtl, 0);
+      rtl = SUBREG_REG (rtl);
 
       /* Fall through.  */
 
@@ -7056,12 +7742,14 @@ mem_loc_descriptor (rtl, mode)
          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.  */
-      mem_loc_result = based_loc_descr (reg_number (rtl), 0);
+      if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
+       mem_loc_result = based_loc_descr (reg_number (rtl), 0);
       break;
 
     case MEM:
       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
-      add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
+      if (mem_loc_result != 0)
+       add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
       break;
 
     case LABEL_REF:
@@ -7070,6 +7758,16 @@ mem_loc_descriptor (rtl, mode)
         pool.  */
     case CONST:
     case SYMBOL_REF:
+      /* Alternatively, the symbol in the constant pool might be referenced
+        by a different symbol.  */
+      if (GET_CODE (rtl) == SYMBOL_REF
+         && CONSTANT_POOL_ADDRESS_P (rtl))
+       {
+         rtx tmp = get_pool_constant (rtl);
+         if (GET_CODE (tmp) == SYMBOL_REF)
+           rtl = tmp;
+       }
+
       mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
       mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
       mem_loc_result->dw_loc_oprnd1.v.val_addr = save_rtx (rtl);
@@ -7077,7 +7775,7 @@ mem_loc_descriptor (rtl, mode)
 
     case PRE_MODIFY:
       /* Extract the PLUS expression nested inside and fall into
-         PLUS code bellow.  */
+         PLUS code below.  */
       rtl = XEXP (rtl, 1);
       goto plus;
 
@@ -7100,14 +7798,14 @@ mem_loc_descriptor (rtl, mode)
       else
        {
          mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
+         if (mem_loc_result == 0)
+           break;
 
          if (GET_CODE (XEXP (rtl, 1)) == CONST_INT
              && INTVAL (XEXP (rtl, 1)) >= 0)
-           {
-             add_loc_descr (&mem_loc_result,
-                            new_loc_descr (DW_OP_plus_uconst,
-                                           INTVAL (XEXP (rtl, 1)), 0));
-           }
+           add_loc_descr (&mem_loc_result,
+                          new_loc_descr (DW_OP_plus_uconst,
+                                         INTVAL (XEXP (rtl, 1)), 0));
          else
            {
              add_loc_descr (&mem_loc_result,
@@ -7119,14 +7817,20 @@ mem_loc_descriptor (rtl, mode)
       break;
 
     case MULT:
-      /* If a pseudo-reg is optimized away, it is possible for it to
-        be replaced with a MEM containing a multiply.  */
-      add_loc_descr (&mem_loc_result,
-                    mem_loc_descriptor (XEXP (rtl, 0), mode));
-      add_loc_descr (&mem_loc_result,
-                    mem_loc_descriptor (XEXP (rtl, 1), mode));
-      add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
-      break;
+      {
+       /* If a pseudo-reg is optimized away, it is possible for it to
+          be replaced with a MEM containing a multiply.  */
+       dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode);
+       dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode);
+
+       if (op0 == 0 || op1 == 0)
+         break;
+
+       mem_loc_result = op0;
+       add_loc_descr (&mem_loc_result, op1);
+       add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
+       break;
+      }
 
     case CONST_INT:
       mem_loc_result = int_loc_descriptor (INTVAL (rtl));
@@ -7144,21 +7848,24 @@ mem_loc_descriptor (rtl, mode)
 
 static dw_loc_descr_ref
 concat_loc_descriptor (x0, x1)
-     register rtx x0, x1;
+     rtx x0, x1;
 {
   dw_loc_descr_ref cc_loc_result = NULL;
+  dw_loc_descr_ref x0_ref = loc_descriptor (x0);
+  dw_loc_descr_ref x1_ref = loc_descriptor (x1);
 
-  if (!is_pseudo_reg (x0)
-      && (GET_CODE (x0) != MEM || !is_pseudo_reg (XEXP (x0, 0))))
-    add_loc_descr (&cc_loc_result, loc_descriptor (x0));
+  if (x0_ref == 0 || x1_ref == 0)
+    return 0;
+
+  cc_loc_result = x0_ref;
   add_loc_descr (&cc_loc_result,
-                new_loc_descr (DW_OP_piece, GET_MODE_SIZE (GET_MODE (x0)), 0));
+                new_loc_descr (DW_OP_piece,
+                               GET_MODE_SIZE (GET_MODE (x0)), 0));
 
-  if (!is_pseudo_reg (x1)
-      && (GET_CODE (x1) != MEM || !is_pseudo_reg (XEXP (x1, 0))))
-    add_loc_descr (&cc_loc_result, loc_descriptor (x1));
+  add_loc_descr (&cc_loc_result, x1_ref);
   add_loc_descr (&cc_loc_result,
-                new_loc_descr (DW_OP_piece, GET_MODE_SIZE (GET_MODE (x1)), 0));
+                new_loc_descr (DW_OP_piece,
+                               GET_MODE_SIZE (GET_MODE (x1)), 0));
 
   return cc_loc_result;
 }
@@ -7167,13 +7874,16 @@ concat_loc_descriptor (x0, x1)
    which is either allocated in a register or in a memory location.  For a
    register, we just generate an OP_REG and the register number.  For a
    memory location we provide a Dwarf postfix expression describing how to
-   generate the (dynamic) address of the object onto the address stack.  */
+   generate the (dynamic) address of the object onto the address stack.
+
+   If we don't know how to describe it, return 0.  */
 
 static dw_loc_descr_ref
 loc_descriptor (rtl)
-     register rtx rtl;
+     rtx rtl;
 {
   dw_loc_descr_ref loc_result = NULL;
+
   switch (GET_CODE (rtl))
     {
     case SUBREG:
@@ -7182,7 +7892,7 @@ loc_descriptor (rtl)
          up an entire register.  For now, just assume that it is
          legitimate to make the Dwarf info refer to the whole register which
          contains the given subreg.  */
-      rtl = XEXP (rtl, 0);
+      rtl = SUBREG_REG (rtl);
 
       /* Fall through.  */
 
@@ -7206,15 +7916,17 @@ loc_descriptor (rtl)
 }
 
 /* Similar, but generate the descriptor from trees instead of rtl.
-   This comes up particularly with variable length arrays.  */
+   This comes up particularly with variable length arrays.  If ADDRESSP
+   is nonzero, we are looking for an address.  Otherwise, we return a
+   value.  If we can't find a value, return 0.  */
 
 static dw_loc_descr_ref
 loc_descriptor_from_tree (loc, addressp)
      tree loc;
      int addressp;
 {
-  dw_loc_descr_ref ret = NULL;
-  int indirect_size = 0;
+  dw_loc_descr_ref ret, ret1;
+  int indirect_p = 0;
   int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
   enum dwarf_location_atom op;
 
@@ -7225,35 +7937,36 @@ loc_descriptor_from_tree (loc, addressp)
   switch (TREE_CODE (loc))
     {
     case ERROR_MARK:
-      break;
+      return 0;
 
     case WITH_RECORD_EXPR:
+    case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
         position of other fields.  We don't try to encode this here.  The
         only user of this is Ada, which encodes the needed information using
         the names of types.  */
-      return ret;
+      return 0;
 
     case VAR_DECL:
     case PARM_DECL:
       {
        rtx rtl = rtl_for_decl_location (loc);
-       enum machine_mode mode = DECL_MODE (loc);
+       enum machine_mode mode = GET_MODE (rtl);
 
        if (rtl == NULL_RTX)
-         break;
+         return 0;
        else if (CONSTANT_P (rtl))
          {
            ret = new_loc_descr (DW_OP_addr, 0, 0);
            ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
            ret->dw_loc_oprnd1.v.val_addr = rtl;
-           indirect_size = GET_MODE_SIZE (mode);
+           indirect_p = 1;
          }
        else
          {
            if (GET_CODE (rtl) == MEM)
              {
-               indirect_size = GET_MODE_SIZE (mode);
+               indirect_p = 1;
                rtl = XEXP (rtl, 0);
              }
            ret = mem_loc_descriptor (rtl, mode);
@@ -7263,28 +7976,40 @@ loc_descriptor_from_tree (loc, addressp)
 
     case INDIRECT_REF:
       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
-      indirect_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (loc)));
+      indirect_p = 1;
       break;
 
+    case COMPOUND_EXPR:
+      return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp);
+
     case NOP_EXPR:
     case CONVERT_EXPR:
     case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
       return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       {
        tree obj, offset;
        HOST_WIDE_INT bitsize, bitpos, bytepos;
        enum machine_mode mode;
        int volatilep;
-       unsigned int alignment;
 
        obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
-                                  &unsignedp, &volatilep, &alignment);
+                                  &unsignedp, &volatilep);
+
+       if (obj == loc)
+         return 0;
+
        ret = loc_descriptor_from_tree (obj, 1);
+       if (ret == 0
+           || bitpos % BITS_PER_UNIT != 0
+           || bitsize % BITS_PER_UNIT != 0)
+         return 0;
 
        if (offset != NULL_TREE)
          {
@@ -7293,24 +8018,8 @@ loc_descriptor_from_tree (loc, addressp)
            add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
          }
 
-       if (addressp)
-         {
-           /* We cannot address anything not on a unit boundary.  */
-           if (bitpos % BITS_PER_UNIT != 0)
-             abort ();
-         }
-       else
-         {
-           if (bitpos % BITS_PER_UNIT != 0
-               || bitsize % BITS_PER_UNIT != 0)
-             {
-               /* ??? We could handle this by loading and shifting etc.
-                  Wait until someone needs it before expending the effort.  */
-               abort ();
-             }
-
-           indirect_size = bitsize / BITS_PER_UNIT;
-         }
+       if (!addressp)
+         indirect_p = 1;
 
        bytepos = bitpos / BITS_PER_UNIT;
        if (bytepos > 0)
@@ -7326,40 +8035,54 @@ loc_descriptor_from_tree (loc, addressp)
     case INTEGER_CST:
       if (host_integerp (loc, 0))
        ret = int_loc_descriptor (tree_low_cst (loc, 0));
+      else
+       return 0;
       break;
 
     case BIT_AND_EXPR:
       op = DW_OP_and;
       goto do_binop;
+
     case BIT_XOR_EXPR:
       op = DW_OP_xor;
       goto do_binop;
+
     case BIT_IOR_EXPR:
       op = DW_OP_or;
       goto do_binop;
+
     case TRUNC_DIV_EXPR:
       op = DW_OP_div;
       goto do_binop;
+
     case MINUS_EXPR:
       op = DW_OP_minus;
       goto do_binop;
+
     case TRUNC_MOD_EXPR:
       op = DW_OP_mod;
       goto do_binop;
+
     case MULT_EXPR:
       op = DW_OP_mul;
       goto do_binop;
+
     case LSHIFT_EXPR:
       op = DW_OP_shl;
       goto do_binop;
+
     case RSHIFT_EXPR:
       op = (unsignedp ? DW_OP_shr : DW_OP_shra);
       goto do_binop;
+
     case PLUS_EXPR:
       if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
          && host_integerp (TREE_OPERAND (loc, 1), 0))
        {
          ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+         if (ret == 0)
+           return 0;
+
          add_loc_descr (&ret,
                         new_loc_descr (DW_OP_plus_uconst,
                                        tree_low_cst (TREE_OPERAND (loc, 1),
@@ -7367,53 +8090,72 @@ loc_descriptor_from_tree (loc, addressp)
                                        0));
          break;
        }
+
       op = DW_OP_plus;
       goto do_binop;
     case LE_EXPR:
       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       break;
+       return 0;
+
       op = DW_OP_le;
       goto do_binop;
+
     case GE_EXPR:
       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       break;
+       return 0;
+
       op = DW_OP_ge;
       goto do_binop;
+
     case LT_EXPR:
       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       break;
+       return 0;
+
       op = DW_OP_lt;
       goto do_binop;
+
     case GT_EXPR:
       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       break;
+       return 0;
+
       op = DW_OP_gt;
       goto do_binop;
+
     case EQ_EXPR:
       op = DW_OP_eq;
       goto do_binop;
+
     case NE_EXPR:
       op = DW_OP_ne;
       goto do_binop;
 
     do_binop:
       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
-      add_loc_descr (&ret, loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0));
+      ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+      if (ret == 0 || ret1 == 0)
+       return 0;
+
+      add_loc_descr (&ret, ret1);
       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
       break;
 
     case BIT_NOT_EXPR:
       op = DW_OP_not;
       goto do_unop;
+
     case ABS_EXPR:
       op = DW_OP_abs;
       goto do_unop;
+
     case NEGATE_EXPR:
       op = DW_OP_neg;
       goto do_unop;
 
     do_unop:
       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+      if (ret == 0)
+       return 0;
+
       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
       break;
 
@@ -7426,21 +8168,26 @@ loc_descriptor_from_tree (loc, addressp)
 
     case COND_EXPR:
       {
+       dw_loc_descr_ref lhs
+         = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+       dw_loc_descr_ref rhs
+         = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
        dw_loc_descr_ref bra_node, jump_node, tmp;
 
        ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+       if (ret == 0 || lhs == 0 || rhs == 0)
+         return 0;
+
        bra_node = new_loc_descr (DW_OP_bra, 0, 0);
        add_loc_descr (&ret, bra_node);
 
-       tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
-       add_loc_descr (&ret, tmp);
+       add_loc_descr (&ret, rhs);
        jump_node = new_loc_descr (DW_OP_skip, 0, 0);
        add_loc_descr (&ret, jump_node);
 
-       tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
-       add_loc_descr (&ret, tmp);
+       add_loc_descr (&ret, lhs);
        bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
-       bra_node->dw_loc_oprnd1.v.val_loc = tmp;
+       bra_node->dw_loc_oprnd1.v.val_loc = lhs;
 
        /* ??? Need a node to point the skip at.  Use a nop.  */
        tmp = new_loc_descr (DW_OP_nop, 0, 0);
@@ -7454,20 +8201,23 @@ loc_descriptor_from_tree (loc, addressp)
       abort ();
     }
 
-  /* If we can't fill the request for an address, die.  */
-  if (addressp && indirect_size == 0)
-    abort ();
+  /* Show if we can't fill the request for an address.  */
+  if (addressp && indirect_p == 0)
+    return 0;
 
   /* If we've got an address and don't want one, dereference.  */
-  if (!addressp && indirect_size > 0)
+  if (!addressp && indirect_p > 0)
     {
-      if (indirect_size > DWARF2_ADDR_SIZE)
-       abort ();
-      if (indirect_size == DWARF2_ADDR_SIZE)
+      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
+
+      if (size > DWARF2_ADDR_SIZE || size == -1)
+       return 0;
+      if (size == DWARF2_ADDR_SIZE)
        op = DW_OP_deref;
       else
        op = DW_OP_deref_size;
-      add_loc_descr (&ret, new_loc_descr (op, indirect_size, 0));
+
+      add_loc_descr (&ret, new_loc_descr (op, size, 0));
     }
 
   return ret;
@@ -7491,9 +8241,9 @@ ceiling (value, boundary)
 
 static inline tree
 field_type (decl)
-     register tree decl;
+     tree decl;
 {
-  register tree type;
+  tree type;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return integer_type_node;
@@ -7511,14 +8261,14 @@ field_type (decl)
 
 static inline unsigned
 simple_type_align_in_bits (type)
-     register tree type;
+     tree type;
 {
   return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;
 }
 
 static inline unsigned
 simple_decl_align_in_bits (decl)
-     register tree decl;
+     tree decl;
 {
   return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
 }
@@ -7531,7 +8281,7 @@ simple_decl_align_in_bits (decl)
 
 static inline unsigned HOST_WIDE_INT
 simple_type_size_in_bits (type)
-     register tree type;
+     tree type;
 {
   tree type_size_tree;
 
@@ -7555,7 +8305,7 @@ simple_type_size_in_bits (type)
 
 static HOST_WIDE_INT
 field_byte_offset (decl)
-     register tree decl;
+     tree decl;
 {
   unsigned int type_align_in_bits;
   unsigned int decl_align_in_bits;
@@ -7681,33 +8431,12 @@ static void
 add_AT_location_description (die, attr_kind, rtl)
      dw_die_ref die;
      enum dwarf_attribute attr_kind;
-     register rtx rtl;
-{
-  /* 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.  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.  */
-
-  if (is_pseudo_reg (rtl)
-      || (GET_CODE (rtl) == MEM
-         && is_pseudo_reg (XEXP (rtl, 0)))
-      /* This can happen for a PARM_DECL with a DECL_INCOMING_RTL which
-        references the internal argument pointer (a pseudo) in a function
-        where all references to the internal argument pointer were
-        eliminated via the optimizers.  */
-      || (GET_CODE (rtl) == MEM
-         && GET_CODE (XEXP (rtl, 0)) == PLUS
-         && is_pseudo_reg (XEXP (XEXP (rtl, 0), 0)))
-      || (GET_CODE (rtl) == CONCAT
-         && is_pseudo_reg (XEXP (rtl, 0))
-         && is_pseudo_reg (XEXP (rtl, 1))))
-    return;
+     rtx rtl;
+{
+  dw_loc_descr_ref descr = loc_descriptor (rtl);
 
-  add_AT_loc (die, attr_kind, loc_descriptor (rtl));
+  if (descr != 0)
+    add_AT_loc (die, attr_kind, descr);
 }
 
 /* Attach the specialized form of location attribute used for data
@@ -7731,31 +8460,73 @@ add_AT_location_description (die, attr_kind, rtl)
 
 static void
 add_data_member_location_attribute (die, decl)
-     register dw_die_ref die;
-     register tree decl;
+     dw_die_ref die;
+     tree decl;
 {
-  register unsigned long offset;
-  register dw_loc_descr_ref loc_descr;
-  register enum dwarf_location_atom op;
+  long offset;
+  dw_loc_descr_ref loc_descr = 0;
 
   if (TREE_CODE (decl) == TREE_VEC)
-    offset = tree_low_cst (BINFO_OFFSET (decl), 0);
+    {
+      /* We're working on the TAG_inheritance for a base class.  */
+
+      if (TREE_VIA_VIRTUAL (decl) && is_cxx ())
+       {
+         /* For C++ virtual bases we can't just use BINFO_OFFSET, as they
+            aren't at a fixed offset from all (sub)objects of the same
+            type.  We need to extract the appropriate offset from our
+            vtable.  The following dwarf expression means
+
+              BaseAddr = ObAddr + *((*ObAddr) - Offset)
+
+            This is specific to the V3 ABI, of course.  */
+
+         dw_loc_descr_ref tmp;
+         /* Make a copy of the object address.  */
+         tmp = new_loc_descr (DW_OP_dup, 0, 0);
+         add_loc_descr (&loc_descr, tmp);
+         /* Extract the vtable address.  */
+         tmp = new_loc_descr (DW_OP_deref, 0, 0);
+         add_loc_descr (&loc_descr, tmp);
+         /* Calculate the address of the offset.  */
+         offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0);
+         if (offset >= 0)
+           abort ();
+         tmp = int_loc_descriptor (-offset);
+         add_loc_descr (&loc_descr, tmp);
+         tmp = new_loc_descr (DW_OP_minus, 0, 0);
+         add_loc_descr (&loc_descr, tmp);
+         /* Extract the offset.  */
+         tmp = new_loc_descr (DW_OP_deref, 0, 0);
+         add_loc_descr (&loc_descr, tmp);
+         /* Add it to the object address.  */
+         tmp = new_loc_descr (DW_OP_plus, 0, 0);
+         add_loc_descr (&loc_descr, tmp);
+       }
+      else
+       offset = tree_low_cst (BINFO_OFFSET (decl), 0);
+    }
   else
     offset = field_byte_offset (decl);
 
-  /* The DWARF2 standard says that we should assume that the structure address
-     is already on the stack, so we can specify a structure field address
-     by using DW_OP_plus_uconst.  */
+  if (! loc_descr)
+    {
+      enum dwarf_location_atom op;
+
+      /* The DWARF2 standard says that we should assume that the structure address
+        is already on the stack, so we can specify a structure field address
+        by using DW_OP_plus_uconst.  */
 
 #ifdef MIPS_DEBUGGING_INFO
-  /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst operator
-     correctly.  It works only if we leave the offset on the stack.  */
-  op = DW_OP_constu;
+      /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst operator
+        correctly.  It works only if we leave the offset on the stack.  */
+      op = DW_OP_constu;
 #else
-  op = DW_OP_plus_uconst;
+      op = DW_OP_plus_uconst;
 #endif
 
-  loc_descr = new_loc_descr (op, offset, 0);
+      loc_descr = new_loc_descr (op, offset, 0);
+    }
   add_AT_loc (die, DW_AT_data_member_location, loc_descr);
 }
 
@@ -7767,8 +8538,8 @@ add_data_member_location_attribute (die, decl)
 
 static void
 add_const_value_attribute (die, rtl)
-     register dw_die_ref die;
-     register rtx rtl;
+     dw_die_ref die;
+     rtx rtl;
 {
   switch (GET_CODE (rtl))
     {
@@ -7782,17 +8553,18 @@ add_const_value_attribute (die, rtl)
        HOST_WIDE_INT val = INTVAL (rtl);
        
        /* ??? We really should be using HOST_WIDE_INT throughout.  */
-       if (val < 0)
-         {
-           if ((long) val != val)
-             abort ();
-           add_AT_int (die, DW_AT_const_value, (long) val);
-         }
+       if (val < 0 && (long) val == val)
+         add_AT_int (die, DW_AT_const_value, (long) val);
+       else if ((unsigned long) val == (unsigned HOST_WIDE_INT) val)
+         add_AT_unsigned (die, DW_AT_const_value, (unsigned long) val);
        else
          {
-           if ((unsigned long) val != (unsigned HOST_WIDE_INT) val)
-             abort ();
-           add_AT_int (die, DW_AT_const_value, (unsigned long) val);
+#if HOST_BITS_PER_LONG * 2 == HOST_BITS_PER_WIDE_INT
+           add_AT_long_long (die, DW_AT_const_value,
+                             val >> HOST_BITS_PER_LONG, val);
+#else
+           abort ();
+#endif
          }
       }
       break;
@@ -7803,11 +8575,11 @@ add_const_value_attribute (die, rtl)
          constant requires more than one word in order to be adequately
          represented.  We output CONST_DOUBLEs as blocks.  */
       {
-       register enum machine_mode mode = GET_MODE (rtl);
+       enum machine_mode mode = GET_MODE (rtl);
 
        if (GET_MODE_CLASS (mode) == MODE_FLOAT)
          {
-           register unsigned length = GET_MODE_SIZE (mode) / 4;
+           unsigned length = GET_MODE_SIZE (mode) / 4;
            long *array = (long *) xmalloc (sizeof (long) * length);
            REAL_VALUE_TYPE rv;
 
@@ -7879,7 +8651,7 @@ static rtx
 rtl_for_decl_location (decl)
      tree decl;
 {
-  register rtx rtl;
+  rtx rtl;
 
   /* 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
@@ -8020,6 +8792,16 @@ rtl_for_decl_location (decl)
 #endif
     }
 
+  /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time
+     constant, and will have been substituted directly into all 
+     expressions that use it.  C does not have such a concept, but
+     C++ and other languages do.  */
+  else if (DECL_INITIAL (decl))
+    {
+      rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
+                        EXPAND_INITIALIZER);
+    }
+
   return rtl;
 }
 
@@ -8036,10 +8818,10 @@ rtl_for_decl_location (decl)
 
 static void
 add_location_or_const_value_attribute (die, decl)
-     register dw_die_ref die;
-     register tree decl;
+     dw_die_ref die;
+     tree decl;
 {
-  register rtx rtl;
+  rtx rtl;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
@@ -8051,6 +8833,11 @@ add_location_or_const_value_attribute (die, decl)
   if (rtl == NULL_RTX)
     return;
 
+  /* If we don't look past the constant pool, we risk emitting a
+     reference to a constant pool entry that isn't referenced from
+     code, and thus is not emitted.  */
+  rtl = avoid_constant_pool_reference (rtl);
+
   switch (GET_CODE (rtl))
     {
     case ADDRESSOF:
@@ -8120,8 +8907,8 @@ tree_add_const_value_attribute (var_die, decl)
 
 static inline void
 add_name_attribute (die, name_string)
-     register dw_die_ref die;
-     register const char *name_string;
+     dw_die_ref die;
+     const char *name_string;
 {
   if (name_string != NULL && *name_string != 0)
     {
@@ -8137,16 +8924,10 @@ add_name_attribute (die, name_string)
 
 static void
 add_bound_info (subrange_die, bound_attr, bound)
-     register dw_die_ref subrange_die;
-     register enum dwarf_attribute bound_attr;
-     register tree bound;
-{
-  /* If this is an Ada unconstrained array type, then don't emit any debug
-     info because the array bounds are unknown.  They are parameterized when
-     the type is instantiated.  */
-  if (contains_placeholder_p (bound))
-    return;
-
+     dw_die_ref subrange_die;
+     enum dwarf_attribute bound_attr;
+     tree bound;
+{
   switch (TREE_CODE (bound))
     {
     case ERROR_MARK:
@@ -8167,6 +8948,7 @@ add_bound_info (subrange_die, bound_attr, bound)
     case CONVERT_EXPR:
     case NOP_EXPR:
     case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
       add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
       break;
 
@@ -8185,7 +8967,7 @@ add_bound_info (subrange_die, bound_attr, bound)
          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
+         comprehend that a missing upper bound specification in an 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.
@@ -8196,9 +8978,9 @@ add_bound_info (subrange_die, bound_attr, bound)
       if (SAVE_EXPR_RTL (bound)
          && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
        {
-         register dw_die_ref ctx = lookup_decl_die (current_function_decl);
-         register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
-         register rtx loc = SAVE_EXPR_RTL (bound);
+         dw_die_ref ctx = lookup_decl_die (current_function_decl);
+         dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
+         rtx loc = SAVE_EXPR_RTL (bound);
 
          /* If the RTL for the SAVE_EXPR is memory, handle the case where
             it references an outer function's frame.  */
@@ -8247,7 +9029,10 @@ add_bound_info (subrange_die, bound_attr, bound)
        if (loc == NULL)
          break;
 
-       ctx = lookup_decl_die (current_function_decl);
+       if (current_function_decl == 0)
+         ctx = comp_unit_die;
+       else
+         ctx = lookup_decl_die (current_function_decl);
 
        decl_die = new_die (DW_TAG_variable, ctx);
        add_AT_flag (decl_die, DW_AT_artificial, 1);
@@ -8265,14 +9050,14 @@ add_bound_info (subrange_die, bound_attr, bound)
 
 static void
 add_subscript_info (type_die, type)
-     register dw_die_ref type_die;
-     register tree type;
+     dw_die_ref type_die;
+     tree type;
 {
 #ifndef MIPS_DEBUGGING_INFO
-  register unsigned dimension_number;
+  unsigned dimension_number;
 #endif
-  register tree lower, upper;
-  register dw_die_ref subrange_die;
+  tree lower, upper;
+  dw_die_ref subrange_die;
 
   /* The GNU compilers represent multidimensional array types as sequences of
      one dimensional array types whose element types are themselves array
@@ -8293,7 +9078,7 @@ add_subscript_info (type_die, type)
        type = TREE_TYPE (type), dimension_number++)
     {
 #endif
-      register tree domain = TYPE_DOMAIN (type);
+      tree domain = TYPE_DOMAIN (type);
 
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
@@ -8346,9 +9131,9 @@ add_subscript_info (type_die, type)
 static void
 add_byte_size_attribute (die, tree_node)
      dw_die_ref die;
-     register tree tree_node;
+     tree tree_node;
 {
-  register unsigned size;
+  unsigned size;
 
   switch (TREE_CODE (tree_node))
     {
@@ -8399,8 +9184,8 @@ add_byte_size_attribute (die, tree_node)
 
 static inline void
 add_bit_offset_attribute (die, decl)
-     register dw_die_ref die;
-     register tree decl;
+     dw_die_ref die;
+     tree decl;
 {
   HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl);
   tree type = DECL_BIT_FIELD_TYPE (decl);
@@ -8450,8 +9235,8 @@ add_bit_offset_attribute (die, decl)
 
 static inline void
 add_bit_size_attribute (die, decl)
-     register dw_die_ref die;
-     register tree decl;
+     dw_die_ref die;
+     tree decl;
 {
   /* Must be a field and a bit field.  */
   if (TREE_CODE (decl) != FIELD_DECL
@@ -8467,8 +9252,8 @@ add_bit_size_attribute (die, decl)
 
 static inline void
 add_prototyped_attribute (die, func_type)
-     register dw_die_ref die;
-     register tree func_type;
+     dw_die_ref die;
+     tree func_type;
 {
   if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89
       && TYPE_ARG_TYPES (func_type) != NULL)
@@ -8481,8 +9266,8 @@ add_prototyped_attribute (die, func_type)
 
 static inline void
 add_abstract_origin_attribute (die, origin)
-     register dw_die_ref die;
-     register tree origin;
+     dw_die_ref die;
+     tree origin;
 {
   dw_die_ref origin_die = NULL;
 
@@ -8517,8 +9302,8 @@ add_abstract_origin_attribute (die, origin)
 
 static inline void
 add_pure_or_virtual_attribute (die, func_decl)
-     register dw_die_ref die;
-     register tree func_decl;
+     dw_die_ref die;
+     tree func_decl;
 {
   if (DECL_VINDEX (func_decl))
     {
@@ -8541,10 +9326,10 @@ add_pure_or_virtual_attribute (die, func_decl)
 
 static void
 add_src_coords_attributes (die, decl)
-     register dw_die_ref die;
-     register tree decl;
+     dw_die_ref die;
+     tree decl;
 {
-  register unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
+  unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
 
   add_AT_unsigned (die, DW_AT_decl_file, file_index);
   add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
@@ -8555,10 +9340,10 @@ add_src_coords_attributes (die, decl)
 
 static void
 add_name_and_src_coords_attributes (die, decl)
-     register dw_die_ref die;
-     register tree decl;
+     dw_die_ref die;
+     tree decl;
 {
-  register tree decl_name;
+  tree decl_name;
 
   decl_name = DECL_NAME (decl);
   if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL)
@@ -8574,6 +9359,15 @@ add_name_and_src_coords_attributes (die, decl)
        add_AT_string (die, DW_AT_MIPS_linkage_name,
                       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
     }
+
+#ifdef VMS_DEBUGGING_INFO
+
+  /* Get the function's name, as described by its RTL.  This may be different
+     from the DECL_NAME name used in the source file.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
+    add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address,
+                save_rtx (XEXP (DECL_RTL (decl), 0)));
+#endif
 }
 
 /* Push a new declaration scope.  */
@@ -8582,26 +9376,16 @@ static void
 push_decl_scope (scope)
      tree scope;
 {
-  /* Make room in the decl_scope_table, if necessary.  */
-  if (decl_scope_table_allocated == decl_scope_depth)
-    {
-      decl_scope_table_allocated += DECL_SCOPE_TABLE_INCREMENT;
-      decl_scope_table
-       = (tree *) xrealloc (decl_scope_table,
-                            decl_scope_table_allocated * sizeof (tree));
-    }
-
-  decl_scope_table[decl_scope_depth] = scope;
-  decl_scope_depth++;
+  VARRAY_PUSH_TREE (decl_scope_table, scope);
 }
 
 /* Pop a declaration scope.  */
 static inline void
 pop_decl_scope ()
 {
-  if (decl_scope_depth <= 0)
+  if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0)
     abort ();
-  --decl_scope_depth;
+  VARRAY_POP (decl_scope_table);
 }
 
 /* Return the DIE for the scope that immediately contains this type.
@@ -8612,12 +9396,12 @@ pop_decl_scope ()
 
 static dw_die_ref
 scope_die_for (t, context_die)
-     register tree t;
-     register dw_die_ref context_die;
+     tree t;
+     dw_die_ref context_die;
 {
-  register dw_die_ref scope_die = NULL;
-  register tree containing_scope;
-  register int i;
+  dw_die_ref scope_die = NULL;
+  tree containing_scope;
+  int i;
 
   /* Non-types always go in the current scope.  */
   if (! TYPE_P (t))
@@ -8643,8 +9427,8 @@ scope_die_for (t, context_die)
         first we check to see if we're in the middle of emitting it
         so we know where the new DIE should go.  */
 
-      for (i = decl_scope_depth - 1; i >= 0; --i)
-       if (decl_scope_table[i] == containing_scope)
+      for (i = VARRAY_ACTIVE_SIZE (decl_scope_table) - 1; i >= 0; --i)
+       if (VARRAY_TREE (decl_scope_table, i) == containing_scope)
          break;
 
       if (i < 0)
@@ -8697,14 +9481,14 @@ class_scope_p (context_die)
 
 static void
 add_type_attribute (object_die, type, decl_const, decl_volatile, context_die)
-     register dw_die_ref object_die;
-     register tree type;
-     register int decl_const;
-     register int decl_volatile;
-     register dw_die_ref context_die;
+     dw_die_ref object_die;
+     tree type;
+     int decl_const;
+     int decl_volatile;
+     dw_die_ref context_die;
 {
-  register enum tree_code code  = TREE_CODE (type);
-  register dw_die_ref type_die  = NULL;
+  enum tree_code code  = TREE_CODE (type);
+  dw_die_ref type_die  = NULL;
 
   /* ??? If this type is an unnamed subrange type of an integral or
      floating-point type, use the inner type.  This is because we have no
@@ -8737,13 +9521,13 @@ add_type_attribute (object_die, type, decl_const, decl_volatile, context_die)
 
 static const char *
 type_tag (type)
-     register tree type;
+     tree type;
 {
-  register const char *name = 0;
+  const char *name = 0;
 
   if (TYPE_NAME (type) != 0)
     {
-      register tree t = 0;
+      tree t = 0;
 
       /* Find the IDENTIFIER_NODE for the type name.  */
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
@@ -8769,7 +9553,7 @@ type_tag (type)
 
 static inline tree
 member_declared_type (member)
-     register tree member;
+     tree member;
 {
   return (DECL_BIT_FIELD_TYPE (member)
          ? DECL_BIT_FIELD_TYPE (member)
@@ -8782,7 +9566,7 @@ member_declared_type (member)
 #if 0
 static const char *
 decl_start_label (decl)
-     register tree decl;
+     tree decl;
 {
   rtx x;
   const char *fnname;
@@ -8805,12 +9589,12 @@ decl_start_label (decl)
 
 static void
 gen_array_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref scope_die = scope_die_for (type, context_die);
-  register dw_die_ref array_die;
-  register tree element_type;
+  dw_die_ref scope_die = scope_die_for (type, context_die);
+  dw_die_ref array_die;
+  tree element_type;
 
   /* ??? The SGI dwarf reader fails for array of array of enum types unless
      the inner array type comes before the outer array type.  Thus we must
@@ -8863,10 +9647,10 @@ gen_array_type_die (type, context_die)
 
 static void
 gen_set_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die
+  dw_die_ref type_die
     = new_die (DW_TAG_set_type, scope_die_for (type, context_die));
 
   equate_type_number_to_die (type, type_die);
@@ -8876,11 +9660,11 @@ gen_set_type_die (type, context_die)
 #if 0
 static void
 gen_entry_point_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
-  register tree origin = decl_ultimate_origin (decl);
-  register dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die);
+  tree origin = decl_ultimate_origin (decl);
+  dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die);
   if (origin != NULL)
     add_abstract_origin_attribute (decl_die, origin);
   else
@@ -8898,20 +9682,11 @@ gen_entry_point_die (decl, context_die)
 #endif
 
 /* Remember a type in the incomplete_types_list.  */
-
 static void
 add_incomplete_type (type)
      tree type;
 {
-  if (incomplete_types == incomplete_types_allocated)
-    {
-      incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
-      incomplete_types_list
-       = (tree *) xrealloc (incomplete_types_list,
-                            sizeof (tree) * incomplete_types_allocated);
-    }
-
-  incomplete_types_list[incomplete_types++] = type;
+  VARRAY_PUSH_TREE (incomplete_types, type);
 }
 
 /* Walk through the list of incomplete types again, trying once more to
@@ -8920,13 +9695,10 @@ add_incomplete_type (type)
 static void
 retry_incomplete_types ()
 {
-  register tree type;
-
-  while (incomplete_types)
+  int i;
+  for (i = VARRAY_ACTIVE_SIZE (incomplete_types) - 1; i >= 0; i--)
     {
-      --incomplete_types;
-      type = incomplete_types_list[incomplete_types];
-      gen_type_die (type, comp_unit_die);
+      gen_type_die (VARRAY_TREE (incomplete_types, i), comp_unit_die);
     }
 }
 
@@ -8934,11 +9706,10 @@ retry_incomplete_types ()
 
 static void
 gen_inlined_enumeration_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die = new_die (DW_TAG_enumeration_type,
-                                         context_die);
+  dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die);
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
   add_abstract_origin_attribute (type_die, type);
@@ -8948,10 +9719,10 @@ gen_inlined_enumeration_type_die (type, context_die)
 
 static void
 gen_inlined_structure_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die);
+  dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die);
 
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
@@ -8962,10 +9733,10 @@ gen_inlined_structure_type_die (type, context_die)
 
 static void
 gen_inlined_union_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die = new_die (DW_TAG_union_type, context_die);
+  dw_die_ref type_die = new_die (DW_TAG_union_type, context_die);
 
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
@@ -8979,10 +9750,10 @@ gen_inlined_union_type_die (type, context_die)
 
 static void
 gen_enumeration_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die = lookup_type_die (type);
+  dw_die_ref type_die = lookup_type_die (type);
 
   if (type_die == NULL)
     {
@@ -9001,7 +9772,7 @@ gen_enumeration_type_die (type, context_die)
      attribute or the DW_AT_element_list attribute.  */
   if (TYPE_SIZE (type))
     {
-      register tree link;
+      tree link;
 
       TREE_ASM_WRITTEN (type) = 1;
       add_byte_size_attribute (type_die, type);
@@ -9016,7 +9787,7 @@ gen_enumeration_type_die (type, context_die)
       for (link = TYPE_FIELDS (type);
           link != NULL; link = TREE_CHAIN (link))
        {
-         register dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die);
+         dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die);
 
          add_name_attribute (enum_die,
                              IDENTIFIER_POINTER (TREE_PURPOSE (link)));
@@ -9051,12 +9822,12 @@ gen_enumeration_type_die (type, context_die)
 
 static dw_die_ref
 gen_formal_parameter_die (node, context_die)
-     register tree node;
-     register dw_die_ref context_die;
+     tree node;
+     dw_die_ref context_die;
 {
-  register dw_die_ref parm_die
+  dw_die_ref parm_die
     = new_die (DW_TAG_formal_parameter, context_die);
-  register tree origin;
+  tree origin;
 
   switch (TREE_CODE_CLASS (TREE_CODE (node)))
     {
@@ -9098,8 +9869,8 @@ gen_formal_parameter_die (node, context_die)
 
 static void
 gen_unspecified_parameters_die (decl_or_type, context_die)
-     register tree decl_or_type ATTRIBUTE_UNUSED;
-     register dw_die_ref context_die;
+     tree decl_or_type ATTRIBUTE_UNUSED;
+     dw_die_ref context_die;
 {
   new_die (DW_TAG_unspecified_parameters, context_die);
 }
@@ -9111,12 +9882,12 @@ gen_unspecified_parameters_die (decl_or_type, context_die)
 
 static void
 gen_formal_types_die (function_or_method_type, context_die)
-     register tree function_or_method_type;
-     register dw_die_ref context_die;
+     tree function_or_method_type;
+     dw_die_ref context_die;
 {
-  register tree link;
-  register tree formal_type = NULL;
-  register tree first_parm_type;
+  tree link;
+  tree formal_type = NULL;
+  tree first_parm_type;
   tree arg;
 
   if (TREE_CODE (function_or_method_type) == FUNCTION_DECL)
@@ -9133,7 +9904,7 @@ gen_formal_types_die (function_or_method_type, context_die)
      DW_TAG_formal_parameter DIE for each one.  */
   for (link = first_parm_type; link; )
     {
-      register dw_die_ref parm_die;
+      dw_die_ref parm_die;
 
       formal_type = TREE_VALUE (link);
       if (formal_type == void_type_node)
@@ -9204,11 +9975,11 @@ gen_type_die_for_member (type, member, context_die)
    of a function which we may later generate inlined and/or
    out-of-line instances of.  */
 
-void
+static void
 dwarf2out_abstract_function (decl)
      tree decl;
 {
-  register dw_die_ref old_die;
+  dw_die_ref old_die;
   tree save_fn;
   tree context;
   int was_abstract = DECL_ABSTRACT (decl);
@@ -9223,10 +9994,13 @@ dwarf2out_abstract_function (decl)
 
   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
      we don't get confused by DECL_ABSTRACT.  */
-  context = decl_class_context (decl);
-  if (context)
-    gen_type_die_for_member
-      (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+  if (debug_info_level > DINFO_LEVEL_TERSE)
+    {
+      context = decl_class_context (decl);
+      if (context)
+       gen_type_die_for_member
+         (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+    }
  
   /* Pretend we've just finished compiling this function.  */
   save_fn = current_function_decl;
@@ -9245,18 +10019,18 @@ dwarf2out_abstract_function (decl)
 
 static void
 gen_subprogram_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
   char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
-  register tree origin = decl_ultimate_origin (decl);
-  register dw_die_ref subr_die;
-  register rtx fp_reg;
-  register tree fn_arg_types;
-  register tree outer_scope;
-  register dw_die_ref old_die = lookup_decl_die (decl);
-  register int declaration = (current_function_decl != decl
-                             || class_scope_p (context_die));
+  tree origin = decl_ultimate_origin (decl);
+  dw_die_ref subr_die;
+  rtx fp_reg;
+  tree fn_arg_types;
+  tree outer_scope;
+  dw_die_ref old_die = lookup_decl_die (decl);
+  int declaration = (current_function_decl != decl
+                    || class_scope_p (context_die));
 
   /* Note that it is possible to have both DECL_ABSTRACT and `declaration'
      be true, if we started to generate the abstract instance of an inline,
@@ -9300,7 +10074,7 @@ gen_subprogram_die (decl, context_die)
             instance, if it has duplicate function definitions.  Ideally,
             we should detect this case and ignore it.  For now, if we have
             already reported an error, any error at all, then assume that
-            we got here because of a input error, not a dwarf2 bug.  */
+            we got here because of an input error, not a dwarf2 bug.  */
          if (errorcount)
            return;
          abort ();
@@ -9347,7 +10121,7 @@ gen_subprogram_die (decl, context_die)
       add_name_and_src_coords_attributes (subr_die, decl);
       if (debug_info_level > DINFO_LEVEL_TERSE)
        {
-         register tree type = TREE_TYPE (decl);
+         tree type = TREE_TYPE (decl);
 
          add_prototyped_attribute (subr_die, type);
          add_type_attribute (subr_die, TREE_TYPE (type), 0, 0, context_die);
@@ -9451,8 +10225,8 @@ gen_subprogram_die (decl, context_die)
   else
     {
       /* Generate DIEs to represent all known formal parameters */
-      register tree arg_decls = DECL_ARGUMENTS (decl);
-      register tree parm;
+      tree arg_decls = DECL_ARGUMENTS (decl);
+      tree parm;
 
       /* When generating DIEs, generate the unspecified_parameters DIE
          instead if we come across the arg "__builtin_va_alist" */
@@ -9467,7 +10241,7 @@ gen_subprogram_die (decl, context_die)
              gen_decl_die (parm, subr_die);
          }
 
-      /* Decide whether we need a unspecified_parameters DIE at the end.
+      /* Decide whether we need an 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
@@ -9525,11 +10299,11 @@ gen_subprogram_die (decl, context_die)
 
 static void
 gen_variable_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
-  register tree origin = decl_ultimate_origin (decl);
-  register dw_die_ref var_die = new_die (DW_TAG_variable, context_die);
+  tree origin = decl_ultimate_origin (decl);
+  dw_die_ref var_die = new_die (DW_TAG_variable, context_die);
 
   dw_die_ref old_die = lookup_decl_die (decl);
   int declaration = (DECL_EXTERNAL (decl)
@@ -9542,6 +10316,7 @@ gen_variable_die (decl, context_die)
   /* ??? Loop unrolling/reorder_blocks should perhaps be rewritten to
      copy decls and set the DECL_ABSTRACT flag on them instead of
      sharing them.  */
+  /* ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
   else if (old_die && TREE_STATIC (decl)
           && get_AT_flag (old_die, DW_AT_declaration) == 1)
     {
@@ -9600,12 +10375,12 @@ gen_variable_die (decl, context_die)
 
 static void
 gen_label_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
-  register tree origin = decl_ultimate_origin (decl);
-  register dw_die_ref lbl_die = new_die (DW_TAG_label, context_die);
-  register rtx insn;
+  tree origin = decl_ultimate_origin (decl);
+  dw_die_ref lbl_die = new_die (DW_TAG_label, context_die);
+  rtx insn;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   if (origin != NULL)
@@ -9644,21 +10419,39 @@ gen_label_die (decl, context_die)
 
 static void
 gen_lexical_block_die (stmt, context_die, depth)
-     register tree stmt;
-     register dw_die_ref context_die;
+     tree stmt;
+     dw_die_ref context_die;
      int depth;
 {
-  register dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die);
+  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die);
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   if (! BLOCK_ABSTRACT (stmt))
     {
-      ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
-                                  BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (stmt_die, DW_AT_low_pc, label);
-      ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
-                                  BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (stmt_die, DW_AT_high_pc, label);
+      if (BLOCK_FRAGMENT_CHAIN (stmt))
+       {
+         tree chain;
+
+         add_AT_range_list (stmt_die, DW_AT_ranges, add_ranges (stmt));
+
+         chain = BLOCK_FRAGMENT_CHAIN (stmt);
+         do
+           {
+             add_ranges (chain);
+             chain = BLOCK_FRAGMENT_CHAIN (chain);
+           }
+         while (chain);
+         add_ranges (NULL);
+       }
+      else
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
+                                      BLOCK_NUMBER (stmt));
+         add_AT_lbl_id (stmt_die, DW_AT_low_pc, label);
+         ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
+                                      BLOCK_NUMBER (stmt));
+         add_AT_lbl_id (stmt_die, DW_AT_high_pc, label);
+       }
     }
 
   decls_for_scope (stmt, stmt_die, depth);
@@ -9668,15 +10461,15 @@ gen_lexical_block_die (stmt, context_die, depth)
 
 static void
 gen_inlined_subroutine_die (stmt, context_die, depth)
-     register tree stmt;
-     register dw_die_ref context_die;
+     tree stmt;
+     dw_die_ref context_die;
      int depth;
 {
   if (! BLOCK_ABSTRACT (stmt))
     {
-      register dw_die_ref subr_die
+      dw_die_ref subr_die
        = new_die (DW_TAG_inlined_subroutine, context_die);
-      register tree decl = block_ultimate_origin (stmt);
+      tree decl = block_ultimate_origin (stmt);
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
       /* Emit info for the abstract instance first, if we haven't yet.  */
@@ -9698,10 +10491,10 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
 
 static void
 gen_field_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
-  register dw_die_ref decl_die = new_die (DW_TAG_member, context_die);
+  dw_die_ref decl_die = new_die (DW_TAG_member, context_die);
 
   add_name_and_src_coords_attributes (decl_die, decl);
   add_type_attribute (decl_die, member_declared_type (decl),
@@ -9736,10 +10529,10 @@ gen_field_die (decl, context_die)
    represent certain things in other languages (e.g. Pascal) someday.  */
 static void
 gen_pointer_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref ptr_die
+  dw_die_ref ptr_die
     = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die));
 
   equate_type_number_to_die (type, ptr_die);
@@ -9753,10 +10546,10 @@ gen_pointer_type_die (type, context_die)
    represent certain things in other languages (e.g. Pascal) someday.  */
 static void
 gen_reference_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref ref_die
+  dw_die_ref ref_die
     = new_die (DW_TAG_reference_type, scope_die_for (type, context_die));
 
   equate_type_number_to_die (type, ref_die);
@@ -9768,10 +10561,10 @@ gen_reference_type_die (type, context_die)
 /* Generate a DIE for a pointer to a member type.  */
 static void
 gen_ptr_to_mbr_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref ptr_die
+  dw_die_ref ptr_die
     = new_die (DW_TAG_ptr_to_member_type, scope_die_for (type, context_die));
 
   equate_type_number_to_die (type, ptr_die);
@@ -9784,11 +10577,12 @@ gen_ptr_to_mbr_type_die (type, context_die)
 
 static dw_die_ref
 gen_compile_unit_die (filename)
-     register const char *filename;
+     const char *filename;
 {
-  register dw_die_ref die;
+  dw_die_ref die;
   char producer[250];
   const char *wd = getpwd ();
+  const char *language_string = lang_hooks.name;
   int language;
 
   die = new_die (DW_TAG_compile_unit, NULL);
@@ -9836,10 +10630,10 @@ gen_compile_unit_die (filename)
 
 static void
 gen_string_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die
+  dw_die_ref type_die
     = new_die (DW_TAG_string_type, scope_die_for (type, context_die));
 
   equate_type_number_to_die (type, type_die);
@@ -9855,8 +10649,8 @@ gen_string_type_die (type, context_die)
 
 static void
 gen_inheritance_die (binfo, context_die)
-     register tree binfo;
-     register dw_die_ref context_die;
+     tree binfo;
+     dw_die_ref context_die;
 {
   dw_die_ref die = new_die (DW_TAG_inheritance, context_die);
 
@@ -9875,10 +10669,10 @@ gen_inheritance_die (binfo, context_die)
 
 static void
 gen_member_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register tree member;
+  tree member;
   dw_die_ref child;
 
   /* If this is not an incomplete type, output descriptions of each of its
@@ -9886,7 +10680,7 @@ gen_member_die (type, context_die)
      members of this record or union type, we will also be trying to output
      DIEs to represent the *types* of those members. However the `type'
      function (above) will specifically avoid generating type DIEs for member
-     types *within* the list of member DIEs for this (containing) type execpt
+     types *within* the list of member DIEs for this (containing) type except
      for those types (of members) which are explicitly marked as also being
      members of this (containing) type themselves.  The g++ front- end can
      force any given type to be treated as a member of some other
@@ -9897,9 +10691,9 @@ gen_member_die (type, context_die)
   /* 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;
+      tree bases = TYPE_BINFO_BASETYPES (type);
+      int n_bases = TREE_VEC_LENGTH (bases);
+      int i;
 
       for (i = 0; i < n_bases; i++)
        gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die);
@@ -9941,12 +10735,12 @@ gen_member_die (type, context_die)
 
 static void
 gen_struct_or_union_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die = lookup_type_die (type);
-  register dw_die_ref scope_die = 0;
-  register int nested = 0;
+  dw_die_ref type_die = lookup_type_die (type);
+  dw_die_ref scope_die = 0;
+  int nested = 0;
   int complete = (TYPE_SIZE (type)
                  && (! TYPE_STUB_DECL (type)
                      || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))));
@@ -9963,7 +10757,7 @@ gen_struct_or_union_type_die (type, context_die)
   if (! type_die || (nested && scope_die == comp_unit_die))
     /* First occurrence of type or toplevel definition of nested class.  */
     {
-      register dw_die_ref old_die = type_die;
+      dw_die_ref old_die = type_die;
 
       type_die = new_die (TREE_CODE (type) == RECORD_TYPE
                          ? DW_TAG_structure_type : DW_TAG_union_type,
@@ -10021,11 +10815,11 @@ gen_struct_or_union_type_die (type, context_die)
 
 static void
 gen_subroutine_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
-  register tree return_type = TREE_TYPE (type);
-  register dw_die_ref subr_die
+  tree return_type = TREE_TYPE (type);
+  dw_die_ref subr_die
     = new_die (DW_TAG_subroutine_type, scope_die_for (type, context_die));
 
   equate_type_number_to_die (type, subr_die);
@@ -10038,11 +10832,11 @@ gen_subroutine_type_die (type, context_die)
 
 static void
 gen_typedef_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
-  register dw_die_ref type_die;
-  register tree origin;
+  dw_die_ref type_die;
+  tree origin;
 
   if (TREE_ASM_WRITTEN (decl))
     return;
@@ -10054,7 +10848,7 @@ gen_typedef_die (decl, context_die)
     add_abstract_origin_attribute (type_die, origin);
   else
     {
-      register tree type;
+      tree type;
       add_name_and_src_coords_attributes (type_die, decl);
       if (DECL_ORIGINAL_TYPE (decl))
        {
@@ -10079,8 +10873,8 @@ gen_typedef_die (decl, context_die)
 
 static void
 gen_type_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
   int need_pop;
 
@@ -10236,8 +11030,8 @@ gen_type_die (type, context_die)
 
 static void
 gen_tagged_type_instantiation_die (type, context_die)
-     register tree type;
-     register dw_die_ref context_die;
+     tree type;
+     dw_die_ref context_die;
 {
   if (type == NULL_TREE || type == error_mark_node)
     return;
@@ -10280,21 +11074,32 @@ gen_tagged_type_instantiation_die (type, context_die)
 
 static void
 gen_block_die (stmt, context_die, depth)
-     register tree stmt;
-     register dw_die_ref context_die;
+     tree stmt;
+     dw_die_ref context_die;
      int depth;
 {
-  register int must_output_die = 0;
-  register tree origin;
-  register tree decl;
-  register enum tree_code origin_code;
+  int must_output_die = 0;
+  tree origin;
+  tree decl;
+  enum tree_code origin_code;
 
   /* Ignore blocks never really used to make RTL.  */
-
   if (stmt == NULL_TREE || !TREE_USED (stmt)
       || (!TREE_ASM_WRITTEN (stmt) && !BLOCK_ABSTRACT (stmt)))
     return;
 
+  /* If the block is one fragment of a non-contiguous block, do not
+     process the variables, since they will have been done by the
+     origin block.  Do process subblocks.  */
+  if (BLOCK_FRAGMENT_ORIGIN (stmt))
+    {
+      tree sub;
+
+      for (sub= BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub))
+       gen_block_die (sub, context_die, depth + 1);
+      return;
+    }
+
   /* 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
@@ -10364,12 +11169,12 @@ gen_block_die (stmt, context_die, depth)
 
 static void
 decls_for_scope (stmt, context_die, depth)
-     register tree stmt;
-     register dw_die_ref context_die;
+     tree stmt;
+     dw_die_ref context_die;
      int depth;
 {
-  register tree decl;
-  register tree subblocks;
+  tree decl;
+  tree subblocks;
 
   /* Ignore blocks never really used to make RTL.  */
   if (stmt == NULL_TREE || ! TREE_USED (stmt))
@@ -10382,7 +11187,7 @@ decls_for_scope (stmt, context_die, depth)
   for (decl = BLOCK_VARS (stmt);
        decl != NULL; decl = TREE_CHAIN (decl))
     {
-      register dw_die_ref die;
+      dw_die_ref die;
 
       if (TREE_CODE (decl) == FUNCTION_DECL)
        die = lookup_decl_die (decl);
@@ -10409,7 +11214,7 @@ decls_for_scope (stmt, context_die, depth)
 
 static inline int
 is_redundant_typedef (decl)
-     register tree decl;
+     tree decl;
 {
   if (TYPE_DECL_IS_STUB (decl))
     return 1;
@@ -10429,10 +11234,10 @@ is_redundant_typedef (decl)
 
 static void
 gen_decl_die (decl, context_die)
-     register tree decl;
-     register dw_die_ref context_die;
+     tree decl;
+     dw_die_ref context_die;
 {
-  register tree origin;
+  tree origin;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
@@ -10597,13 +11402,28 @@ dwarf2out_add_library_unit_info (filename, context_list)
     }
 }
 
+/* Debug information for a global DECL.  Called from toplev.c after
+   compilation proper has finished.  */
+static void
+dwarf2out_global_decl (decl)
+     tree decl;
+{
+  /* Output DWARF2 information for file-scope tentative data object
+     declarations, file-scope (extern) function declarations (which
+     had no corresponding body) and file-scope tagged type
+     declarations and definitions which have not yet been forced out.  */
+
+  if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+    dwarf2out_decl (decl);
+}
+
 /* Write the debugging output for DECL.  */
 
 void
 dwarf2out_decl (decl)
-     register tree decl;
+     tree decl;
 {
-  register dw_die_ref context_die = comp_unit_die;
+  dw_die_ref context_die = comp_unit_die;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
@@ -10715,9 +11535,10 @@ dwarf2out_decl (decl)
 /* Output a marker (i.e. a label) for the beginning of the generated code for
    a lexical block.  */
 
-void
-dwarf2out_begin_block (blocknum)
-     register unsigned blocknum;
+static void
+dwarf2out_begin_block (line, blocknum)
+     unsigned int line ATTRIBUTE_UNUSED;
+     unsigned int blocknum;
 {
   function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
@@ -10726,9 +11547,10 @@ dwarf2out_begin_block (blocknum)
 /* Output a marker (i.e. a label) for the end of the generated code for a
    lexical block.  */
 
-void
-dwarf2out_end_block (blocknum)
-     register unsigned blocknum;
+static void
+dwarf2out_end_block (line, blocknum)
+     unsigned int line ATTRIBUTE_UNUSED;
+     unsigned int blocknum;
 {
   function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
@@ -10741,7 +11563,7 @@ dwarf2out_end_block (blocknum)
    as we would end up with orphans, and in the presence of scheduling
    we may end up calling them anyway.  */
 
-int
+static bool
 dwarf2out_ignore_block (block)
      tree block;
 {
@@ -10768,7 +11590,7 @@ static unsigned
 lookup_filename (file_name)
      const char *file_name;
 {
-  register unsigned i;
+  unsigned i;
 
   /* ??? Why isn't DECL_SOURCE_FILE left null instead.  */
   if (strcmp (file_name, "<internal>") == 0
@@ -10825,15 +11647,20 @@ init_file_table ()
    and record information relating to this source line, in
    'line_info_table' for later output of the .debug_line section.  */
 
-void
-dwarf2out_line (filename, line)
-     register const char *filename;
-     register unsigned line;
+static void
+dwarf2out_source_line (line, filename)
+     unsigned int line;
+     const char *filename;
 {
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     {
       function_section (current_function_decl);
 
+      /* If requested, emit something human-readable.  */
+      if (flag_debug_asm)
+       fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START,
+                filename, line);
+
       if (DWARF2_ASM_LINE_DEBUG_INFO)
        {
          unsigned file_num = lookup_filename (filename);
@@ -10850,12 +11677,9 @@ dwarf2out_line (filename, line)
        }
       else if (DECL_SECTION_NAME (current_function_decl))
        {
-         register dw_separate_line_info_ref line_info;
+         dw_separate_line_info_ref line_info;
          ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL,
                                     separate_line_info_table_in_use);
-         if (flag_debug_asm)
-           fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START,
-                    filename, line);
 
          /* expand the line info table if necessary */
          if (separate_line_info_table_in_use
@@ -10878,13 +11702,10 @@ dwarf2out_line (filename, line)
        }
       else
        {
-         register dw_line_info_ref line_info;
+         dw_line_info_ref line_info;
 
          ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
                                     line_info_table_in_use);
-         if (flag_debug_asm)
-           fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START,
-                    filename, line);
 
          /* Expand the line info table if necessary.  */
          if (line_info_table_in_use == line_info_table_allocated)
@@ -10905,12 +11726,12 @@ dwarf2out_line (filename, line)
     }
 }
 
-/* Record the beginning of a new source file, for later output
-   of the .debug_macinfo section.  At present, unimplemented.  */
+/* Record the beginning of a new source file.  */
 
-void
-dwarf2out_start_source_file (filename)
-     register const char *filename ATTRIBUTE_UNUSED;
+static void
+dwarf2out_start_source_file (lineno, filename)
+     unsigned int lineno;
+     const char *filename;
 {
   if (flag_eliminate_dwarf2_dups)
     {
@@ -10918,55 +11739,82 @@ dwarf2out_start_source_file (filename)
       dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die);
       add_AT_string (bincl_die, DW_AT_name, filename);
     }
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
+      dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
+      dw2_asm_output_data_uleb128 (lineno, "Included from line number %d",
+                                  lineno);
+      dw2_asm_output_data_uleb128 (lookup_filename (filename),
+                                  "Filename we just started");
+    }
 }
 
-/* Record the end of a source file, for later output
-   of the .debug_macinfo section.  At present, unimplemented.  */
+/* Record the end of a source file.  */
 
-void
-dwarf2out_end_source_file ()
+static void
+dwarf2out_end_source_file (lineno)
+     unsigned int lineno ATTRIBUTE_UNUSED;
 {
   if (flag_eliminate_dwarf2_dups)
     {
       /* Record the end of the file for break_out_includes.  */
       new_die (DW_TAG_GNU_EINCL, comp_unit_die);
     }
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
+      dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+    }
 }
 
-/* Called from check_newline in c-parse.y.  The `buffer' parameter contains
+/* Called from debug_define in toplev.c.  The `buffer' parameter contains
    the tail part of the directive line, i.e. the part which is past the
    initial whitespace, #, whitespace, directive-name, whitespace part.  */
 
-void
+static void
 dwarf2out_define (lineno, buffer)
-     register unsigned lineno ATTRIBUTE_UNUSED;
-     register const char *buffer ATTRIBUTE_UNUSED;
+     unsigned lineno ATTRIBUTE_UNUSED;
+     const char *buffer ATTRIBUTE_UNUSED;
 {
   static int initialized = 0;
   if (!initialized)
     {
-      dwarf2out_start_source_file (primary_filename);
+      dwarf2out_start_source_file (0, primary_filename);
       initialized = 1;
     }
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
+      dw2_asm_output_data (1, DW_MACINFO_define, "Define macro");
+      dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno);
+      dw2_asm_output_nstring (buffer, -1, "The macro");
+    }
 }
 
-/* Called from check_newline in c-parse.y.  The `buffer' parameter contains
+/* Called from debug_undef in toplev.c.  The `buffer' parameter contains
    the tail part of the directive line, i.e. the part which is past the
    initial whitespace, #, whitespace, directive-name, whitespace part.  */
 
-void
+static void
 dwarf2out_undef (lineno, buffer)
-     register unsigned lineno ATTRIBUTE_UNUSED;
-     register const char *buffer ATTRIBUTE_UNUSED;
+     unsigned lineno ATTRIBUTE_UNUSED;
+     const char *buffer ATTRIBUTE_UNUSED;
 {
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
+      dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro");
+      dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno);
+      dw2_asm_output_nstring (buffer, -1, "The macro");
+    }
 }
 
 /* Set up for Dwarf output at the start of compilation.  */
 
-void
-dwarf2out_init (asm_out_file, main_input_filename)
-     register FILE *asm_out_file;
-     register const char *main_input_filename;
+static void
+dwarf2out_init (main_input_filename)
+     const char *main_input_filename;
 {
   init_file_table ();
 
@@ -10985,10 +11833,8 @@ dwarf2out_init (asm_out_file, main_input_filename)
   decl_die_table_in_use = 0;
 
   /* Allocate the initial hunk of the decl_scope_table.  */
-  decl_scope_table
-    = (tree *) xcalloc (DECL_SCOPE_TABLE_INCREMENT, sizeof (tree));
-  decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT;
-  decl_scope_depth = 0;
+  VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
+  ggc_add_tree_varray_root (&decl_scope_table, 1);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
   abbrev_die_table
@@ -11013,41 +11859,92 @@ dwarf2out_init (asm_out_file, main_input_filename)
      invoked when the given (base) source file was compiled.  */
   comp_unit_die = gen_compile_unit_die (main_input_filename);
 
+  VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types");
+  ggc_add_tree_varray_root (&incomplete_types, 1);
+
   VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
   ggc_add_rtx_varray_root (&used_rtx_varray, 1);
 
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
-  ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
+                              DEBUG_ABBREV_SECTION_LABEL, 0);
   if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
     ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
   else
-    strcpy (text_section_label, stripattributes (TEXT_SECTION));
+    strcpy (text_section_label, stripattributes (TEXT_SECTION_NAME));
   ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
                               DEBUG_INFO_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
                               DEBUG_LINE_SECTION_LABEL, 0);
-
-  ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
+  ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
+                              DEBUG_RANGES_SECTION_LABEL, 0);
+  named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG);
   ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
+  named_section_flags (DEBUG_INFO_SECTION, SECTION_DEBUG);
+  ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
+  named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG);
+  ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
+      ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
+                                  DEBUG_MACINFO_SECTION_LABEL, 0);
+      ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
+    }
+
   if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
+      text_section ();
       ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
     }
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
-  ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
-  ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
+}
+
+/* Allocate a string in .debug_str hash table.  */
+
+static hashnode
+indirect_string_alloc (tab)
+     hash_table *tab ATTRIBUTE_UNUSED;
+{
+  struct indirect_string_node *node;
+
+  node = xmalloc (sizeof (struct indirect_string_node));
+  node->refcount = 0;
+  node->form = 0;
+  node->label = NULL;
+  return (hashnode) node;
+}
+
+/* A helper function for dwarf2out_finish called through
+   ht_forall.  Emit one queued .debug_str string.  */
+
+static int
+output_indirect_string (pfile, h, v)
+     struct cpp_reader *pfile ATTRIBUTE_UNUSED;
+     hashnode h;
+     const PTR v ATTRIBUTE_UNUSED;
+{
+  struct indirect_string_node *node;
+
+  node = (struct indirect_string_node *) h;
+  if (node->form == DW_FORM_strp)
+    {
+      named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS);
+      ASM_OUTPUT_LABEL (asm_out_file, node->label);
+      assemble_string ((const char *) HT_STR (&node->id),
+                      HT_LEN (&node->id) + 1);
+    }
+  return 1;
 }
 
 /* Output stuff that dwarf requires at the end of every file,
    and generate the DWARF-2 debugging info.  */
 
-void
-dwarf2out_finish ()
+static void
+dwarf2out_finish (input_filename)
+     const char *input_filename ATTRIBUTE_UNUSED;
 {
   limbo_die_node *node, *next_node;
-  dw_die_ref die;
+  dw_die_ref die = 0;
 
   /* Traverse the limbo die list, and add parent/child links.  The only
      dies without parents that should be here are concrete instances of
@@ -11066,6 +11963,9 @@ dwarf2out_finish ()
            add_child_die (origin->die_parent, die);
          else if (die == comp_unit_die)
            ;
+         else if (errorcount > 0 || sorrycount > 0)
+           /* It's OK to be confused by errors in the input.  */
+           add_child_die (comp_unit_die, die);
          else
            abort ();
        }
@@ -11093,44 +11993,51 @@ dwarf2out_finish ()
     add_sibling_attributes (node->die);
 
   /* Output a terminator label for the .text section.  */
-  ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
+  text_section ();
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
 
-#if 0
-  /* Output a terminator label for the .data section.  */
-  ASM_OUTPUT_SECTION (asm_out_file, DATA_SECTION);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, DATA_END_LABEL, 0);
-
-  /* Output a terminator label for the .bss section.  */
-  ASM_OUTPUT_SECTION (asm_out_file, BSS_SECTION);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0);
-#endif
-
-  /* Output the source line correspondence table.  */
-  if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
+  /* Output the source line correspondence table.  We must do this
+     even if there is no line information.  Otherwise, on an empty
+     translation unit, we will generate a present, but empty,
+     .debug_info section.  IRIX 6.5 `nm' will then complain when
+     examining the file.  */
+  if (! DWARF2_ASM_LINE_DEBUG_INFO)
     {
-      if (! DWARF2_ASM_LINE_DEBUG_INFO)
-       {
-         ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
-         output_line_info ();
-       }
+      named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG);
+      output_line_info ();
+    }
 
-      /* We can only use the low/high_pc attributes if all of the code
-        was in .text.  */
-      if (separate_line_info_table_in_use == 0)
-       {
-         add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
-         add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
-       }
+  /* Output location list section if necessary.  */
+  if (have_location_lists)
+    {
+      /* Output the location lists info.  */
+      named_section_flags (DEBUG_LOC_SECTION, SECTION_DEBUG);
+      ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
+                                  DEBUG_LOC_SECTION_LABEL, 0);
+      ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
+      output_location_lists (die);
+      have_location_lists = 0;
+    }
 
-      add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list,
-                        debug_line_section_label);
+  /* We can only use the low/high_pc attributes if all of the code was
+     in .text.  */
+  if (separate_line_info_table_in_use == 0)
+    {
+      add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
+      add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
     }
+  /* And if it wasn't, we need to give .debug_loc and .debug_ranges
+     an appropriate "base address".  Use zero so that these addresses
+     become absolute.  */
+  else if (have_location_lists || ranges_table_in_use)
+    add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx);
 
-#if 0 /* unimplemented */
-  if (debug_info_level >= DINFO_LEVEL_VERBOSE && primary)
-    add_AT_unsigned (die, DW_AT_macro_info, 0);
-#endif
+  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+    add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list,
+                      debug_line_section_label);
+
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    add_AT_lbl_offset (comp_unit_die, DW_AT_macro_info, macinfo_section_label);
 
   /* Output all of the compilation units.  We put the main one last so that
      the offsets are available to output_pubnames.  */
@@ -11139,13 +12046,13 @@ dwarf2out_finish ()
   output_comp_unit (comp_unit_die);
 
   /* Output the abbreviation table.  */
-  ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
+  named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG);
   output_abbrev_section ();
 
   if (pubname_table_in_use)
     {
       /* Output public names table.  */
-      ASM_OUTPUT_SECTION (asm_out_file, PUBNAMES_SECTION);
+      named_section_flags (DEBUG_PUBNAMES_SECTION, SECTION_DEBUG);
       output_pubnames ();
     }
 
@@ -11154,8 +12061,28 @@ dwarf2out_finish ()
   if (fde_table_in_use)
     {
       /* Output the address range information.  */
-      ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);
+      named_section_flags (DEBUG_ARANGES_SECTION, SECTION_DEBUG);
       output_aranges ();
     }
+
+  /* Output ranges section if necessary.  */
+  if (ranges_table_in_use)
+    {
+      named_section_flags (DEBUG_RANGES_SECTION, SECTION_DEBUG);
+      ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
+      output_ranges ();
+    }
+
+  /* Have to end the primary source file.  */
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    { 
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
+      dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+    }
+
+  /* If we emitted any DW_FORM_strp form attribute, output string
+     table too.  */
+  if (debug_str_hash)
+    ht_forall (debug_str_hash, output_indirect_string, NULL);
 }
-#endif /* DWARF2_DEBUGGING_INFO */
+#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */