OSDN Git Service

* config/m68hc11/m68hc11.c (m68hc11_gen_highpart): Don't use
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index f791538..13a7e57 100644 (file)
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include "regs.h"
 #include "insn-config.h"
 #include "reload.h"
+#include "function.h"
 #include "output.h"
 #include "expr.h"
 #include "except.h"
@@ -55,6 +56,12 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "md5.h"
 #include "tm_p.h"
+#include "diagnostic.h"
+#include "debug.h"
+
+#ifdef DWARF2_DEBUGGING_INFO
+static void dwarf2out_source_line      PARAMS ((unsigned int, const char *));
+#endif
 
 /* DWARF2 Abbreviation Glossary:
    CFA = Canonical Frame Address
@@ -86,11 +93,18 @@ dwarf2out_do_frame ()
 #endif
 #ifdef DWARF2_UNWIND_INFO
          || flag_unwind_tables
-         || (flag_exceptions && ! exceptions_via_longjmp)
+         || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)
 #endif
          );
 }
 
+/* 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;
+
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
 /* How to start an assembler comment.  */
@@ -150,7 +164,9 @@ typedef struct dw_fde_struct
   const char *dw_fde_current_label;
   const char *dw_fde_end;
   dw_cfi_ref dw_fde_cfi;
-  int nothrow;
+  unsigned funcdef_number;
+  unsigned nothrow : 1;
+  unsigned uses_eh_lsda : 1;
 }
 dw_fde_node;
 
@@ -212,13 +228,6 @@ 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.  */
-static 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
@@ -238,7 +247,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));
@@ -280,8 +289,8 @@ static void def_cfa_1                       PARAMS ((const char *, dw_cfa_location *));
 #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
@@ -356,7 +365,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).  */
 
@@ -395,9 +404,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));
     }
 }
 
@@ -951,7 +958,7 @@ dwarf2out_stack_adjust (insn)
   long offset;
   const char *label;
 
-  if (! asynchronous_exceptions && GET_CODE (insn) == CALL_INSN)
+  if (! flag_non_call_exceptions && GET_CODE (insn) == CALL_INSN)
     {
       /* Extract the size of the args from the CALL rtx itself.  */
 
@@ -968,7 +975,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 (! asynchronous_exceptions
+  else if (! flag_non_call_exceptions
           && cfa.reg != STACK_POINTER_REGNUM)
     return;
 
@@ -1130,11 +1137,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
@@ -1143,9 +1152,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
 
@@ -1154,26 +1163,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))
@@ -1205,30 +1218,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)
@@ -1288,10 +1302,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 */
@@ -1317,10 +1334,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;
@@ -1340,7 +1360,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;
@@ -1350,7 +1370,7 @@ dwarf2out_frame_debug_expr (expr, label)
            }
          else
            {
-             if (GET_CODE (src) != PLUS)
+             if (GET_CODE (src) == MINUS)
                abort ();
 
              /* Rule 4 */
@@ -1360,27 +1380,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;
 
@@ -1401,26 +1428,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 ();
@@ -1467,23 +1486,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:
@@ -1584,9 +1618,10 @@ dwarf2out_frame_debug (insn)
 /* Output a Call Frame Information opcode and its operand(s).  */
 
 static void
-output_cfi (cfi, fde)
+output_cfi (cfi, fde, for_eh)
      register dw_cfi_ref cfi;
      register dw_fde_ref fde;
+     int for_eh;
 {
   if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
     {
@@ -1618,8 +1653,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,
@@ -1680,26 +1721,30 @@ static void
 output_call_frame_info (for_eh)
      int for_eh;
 {
-  register unsigned long i;
+  register unsigned int i;
   register dw_fde_ref fde;
   register dw_cfi_ref cfi;
   char l1[20], l2[20];
-#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-  char ld[20];
-#endif
-
-  /* Do we want to include a pointer to the exception table?  */
-  int eh_ptr = for_eh && exception_table_p ();
+  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;
       for (i = 0; i < fde_table_in_use; ++i)
-       if (! fde_table[i].nothrow)
-         goto found;
-      return;
-    found:;
+       if (fde_table[i].uses_eh_lsda)
+         any_eh_needed = any_lsda_needed = 1;
+       else if (! fde_table[i].nothrow)
+         any_eh_needed = 1;
+
+      if (! any_eh_needed)
+       return;
     }
 
   /* We're going to be generating comments, so turn on app.  */
@@ -1714,26 +1759,20 @@ output_call_frame_info (for_eh)
       tree label = get_file_function_name ('F');
 
       force_data_section ();
-      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE));
+      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
       assemble_label ("__FRAME_BEGIN__");
     }
   else
-    ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
+    ASM_OUTPUT_SECTION (asm_out_file, DEBUG_FRAME_SECTION);
 
   /* Output the CIE.  */
   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
   ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
-#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-  ASM_GENERATE_INTERNAL_LABEL (ld, CIE_LENGTH_LABEL, for_eh);
-  dw2_asm_output_offset (for_eh ? 4 : DWARF_OFFSET_SIZE, ld,
-                       "Length of Common Information Entry");
-#else
   dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
                        "Length of Common Information Entry");
-#endif
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
   /* Now that the CIE pointer is PC-relative for EH,
@@ -1744,20 +1783,71 @@ output_call_frame_info (for_eh)
 
   dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version");
 
-  if (eh_ptr)
-    {
-      /* The CIE contains a pointer to the exception region info for the
-         frame.  Make the augmentation string three bytes (including the
-         trailing null) so the pointer is 4-byte aligned.  The Solaris ld
-         can't handle unaligned relocs.  */
-      dw2_asm_output_nstring ("eh", -1, "CIE Augmentation");
-      dw2_asm_output_addr (DWARF2_ADDR_SIZE, "__EXCEPTION_TABLE__",
-                          "pointer to exception region info");
-    }
-  else
+  augmentation[0] = 0;
+  augmentation_size = 0;
+  if (for_eh)
     {
-      dw2_asm_output_data (1, 0, "CIE Augmentation (none)");
+      char *p;
+
+      /* Augmentation:
+        z      Indicates that a uleb128 is present to size the
+               augmentation section.
+        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)
+       {
+         *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");
 
   dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor");
 
@@ -1766,38 +1856,46 @@ output_call_frame_info (for_eh)
 
   dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
 
+  if (augmentation[0])
+    {
+      dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
+      if (eh_personality_libfunc)
+       {
+         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);
-#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-  ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1);
-  if (flag_debug_asm)
-    fprintf (asm_out_file, "\t%s CIE Length Symbol", ASM_COMMENT_START);
-  fputc ('\n', asm_out_file);
-#endif
 
   /* Loop through all of the FDE's.  */
   for (i = 0; i < fde_table_in_use; ++i)
     {
       fde = &fde_table[i];
 
-      /* Don't emit EH unwind info for leaf functions.  */
-      if (for_eh && fde->nothrow)
+      /* Don't emit EH unwind info for leaf functions that don't need it.  */
+      if (for_eh && fde->nothrow && ! fde->uses_eh_lsda)
        continue;
 
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
       ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2);
       ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2);
-#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-      ASM_GENERATE_INTERNAL_LABEL (ld, FDE_LENGTH_LABEL, for_eh + i * 2);
-      dw2_asm_output_offset (for_eh ? 4 : DWARF_OFFSET_SIZE, ld, "FDE Length");
-#else
       dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
                            "FDE Length");
-#endif
       ASM_OUTPUT_LABEL (asm_out_file, l1);
 
       /* ??? This always emits a 4 byte offset when for_eh is true, but it
@@ -1812,30 +1910,78 @@ output_call_frame_info (for_eh)
        dw2_asm_output_delta (4, l1, "__FRAME_BEGIN__", "FDE CIE offset");
       else
        dw2_asm_output_offset (DWARF_OFFSET_SIZE,
-                              stripattributes (FRAME_SECTION),
+                              stripattributes (DEBUG_FRAME_SECTION),
                               "FDE CIE offset");
 
-      dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
-                          "FDE initial location");
+      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])
+       {
+         if (any_lsda_needed)
+           {
+             int size = size_of_encoded_value (lsda_encoding);
 
-      dw2_asm_output_delta (DWARF2_ADDR_SIZE, fde->dw_fde_end,
-                           fde->dw_fde_begin, "FDE address range");
+             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_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);
-#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-      ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1);
-      if (flag_debug_asm)
-       fprintf (asm_out_file, "\t%s FDE Length Symbol", ASM_COMMENT_START);
-      fputc ('\n', asm_out_file);
-#endif
     }
 
 #ifndef EH_FRAME_SECTION
@@ -1857,19 +2003,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;
 
+  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)
     {
@@ -1888,9 +2057,18 @@ dwarf2out_begin_prologue ()
   fde->dw_fde_current_label = NULL;
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
+  fde->funcdef_number = current_funcdef_number;
   fde->nothrow = current_function_nothrow;
+  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
@@ -1936,11 +2114,11 @@ dwarf2out_frame_finish ()
 #ifdef MIPS_DEBUGGING_INFO
   if (write_symbols == DWARF2_DEBUG)
     output_call_frame_info (0);
-  if (flag_unwind_tables || (flag_exceptions && ! exceptions_via_longjmp))
+  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 && ! exceptions_via_longjmp))
+      || flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS))
     output_call_frame_info (1);
 #endif
 }
@@ -1951,6 +2129,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
@@ -1960,6 +2139,7 @@ typedef enum
 {
   dw_val_class_addr,
   dw_val_class_loc,
+  dw_val_class_loc_list,
   dw_val_class_const,
   dw_val_class_unsigned_const,
   dw_val_class_long_long,
@@ -2001,6 +2181,7 @@ typedef struct dw_val_struct
   union
     {
       rtx val_addr;
+      dw_loc_list_ref  val_loc_list;
       dw_loc_descr_ref val_loc;
       long int val_int;
       long unsigned val_unsigned;
@@ -2032,6 +2213,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,
@@ -2370,6 +2564,7 @@ new_loc_descr (op, oprnd1, oprnd2)
   return descr;
 }
 
+
 /* Add a location description term to a location description expression.  */
 
 static inline void
@@ -2819,6 +3014,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.  */
@@ -3124,6 +3360,9 @@ static unsigned arange_table_in_use;
    arange_table.  */
 #define ARANGE_TABLE_INCREMENT 64
 
+/* Whether we have location lists that need outputting */
+static unsigned have_location_lists;
+
 /* A pointer to the base of a list of incomplete types which might be
    completed at some later time.  */
 
@@ -3194,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));
@@ -3241,11 +3483,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 void output_location_lists      PARAMS ((dw_die_ref));
 static unsigned long size_of_string    PARAMS ((const char *));
 static int constant_size               PARAMS ((long unsigned));
 static unsigned long size_of_die       PARAMS ((dw_die_ref));
@@ -3357,31 +3599,39 @@ 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 PUBNAMES_SECTION
-#define PUBNAMES_SECTION       ".debug_pubnames"
+#ifndef DEBUG_PUBNAMES_SECTION
+#define DEBUG_PUBNAMES_SECTION ".debug_pubnames"
 #endif
-#ifndef STR_SECTION
-#define STR_SECTION            ".debug_str"
+#ifndef DEBUG_STR_SECTION
+#define DEBUG_STR_SECTION      ".debug_str"
 #endif
 
 /* Standard ELF section names for compiled code and data.  */
@@ -3399,18 +3649,23 @@ static int file_info_cmp                PARAMS ((const void *, const void *));
    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 ABBREV_SECTION_LABEL
-#define ABBREV_SECTION_LABEL     "Ldebug_abbrev"
+#ifndef DEBUG_ABBREV_SECTION_LABEL
+#define DEBUG_ABBREV_SECTION_LABEL     "Ldebug_abbrev"
+#endif
+#ifndef DEBUG_LOC_SECTION_LABEL
+#define DEBUG_LOC_SECTION_LABEL                "Ldebug_loc"
+#endif
+#ifndef DEBUG_MACINFO_SECTION_LABEL
+#define DEBUG_MACINFO_SECTION_LABEL     "Ldebug_macinfo"
 #endif
-
 /* Definitions of defaults for formats and names of various special
    (artificial) labels which may be generated within this file (when the -g
    options is used and DWARF_DEBUGGING_INFO is in effect.
@@ -3422,7 +3677,8 @@ 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];
 #ifndef TEXT_END_LABEL
 #define TEXT_END_LABEL         "Letext"
 #endif
@@ -3484,7 +3740,7 @@ is_pseudo_reg (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
@@ -4256,6 +4512,34 @@ AT_loc (a)
   abort ();
 }
 
+static inline void
+add_AT_loc_list (die, attr_kind, loc_list)
+     register dw_die_ref die;
+     register enum dwarf_attribute attr_kind;
+     register dw_loc_list_ref loc_list;
+{
+  register 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_loc_list;
+  attr->dw_attr_val.v.val_loc_list = loc_list;
+  add_dwarf_attr (die, attr);
+  have_location_lists = 1;
+}
+
+static inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref));
+
+static inline dw_loc_list_ref
+AT_loc_list (a)
+     register 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
@@ -4733,6 +5017,9 @@ print_die (die, outfile)
        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_const:
          fprintf (outfile, "%ld", AT_int (a));
          break;
@@ -5127,18 +5414,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);
 }
 
@@ -5160,7 +5448,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)
@@ -5245,6 +5533,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)
+     register 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
@@ -5256,7 +5562,7 @@ build_abbrev_table (die)
      register dw_die_ref die;
 {
   register unsigned long abbrev_id;
-  register unsigned long n_alloc;
+  register unsigned int n_alloc;
   register dw_die_ref c;
   register dw_attr_ref d_attr, a_attr;
 
@@ -5383,6 +5689,9 @@ size_of_die (die)
            size += lsize;
          }
          break;
+       case dw_val_class_loc_list:
+         size += DWARF_OFFSET_SIZE;
+         break;
        case dw_val_class_const:
          size += size_of_sleb128 (AT_int (a));
          break;
@@ -5518,6 +5827,10 @@ value_format (a)
     {
     case dw_val_class_addr:
       return DW_FORM_addr;
+    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))))
        {
@@ -5636,6 +5949,88 @@ 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)
+     register dw_loc_descr_ref expr;
+     register const char *begin;
+     register const char *end;
+     register const char *section;
+     register unsigned gensym;
+{
+  register 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)
+     register dw_loc_list_ref *list_head;
+     register dw_loc_descr_ref descr;
+     register const char *begin;
+     register const char *end;
+     register const char *section;
+{
+  register 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)
+     register dw_loc_list_ref list_head;
+{
+  register dw_loc_list_ref curr=list_head;
+  ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
+  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)
+    {
+      int 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.  */
+      dw2_asm_output_data (constant_size (size), 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.  */
 
@@ -5726,7 +6121,14 @@ output_die (die)
        case dw_val_class_flag:
          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, name);
+         }
+         break;
        case dw_val_class_die_ref:
          if (AT_ref_external (a))
            {
@@ -5804,10 +6206,13 @@ 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);
@@ -6768,22 +7173,35 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
 
   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)
@@ -6791,7 +7209,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.  */
@@ -6844,6 +7262,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);
@@ -7028,7 +7450,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.  */
 
@@ -7060,6 +7482,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);
@@ -7067,7 +7499,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;
 
@@ -7172,7 +7604,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.  */
 
@@ -7265,6 +7697,7 @@ loc_descriptor_from_tree (loc, addressp)
     case COMPONENT_REF:
     case BIT_FIELD_REF:
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       {
        tree obj, offset;
        HOST_WIDE_INT bitsize, bitpos, bytepos;
@@ -9194,7 +9627,7 @@ 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;
 {
@@ -9213,10 +9646,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;
@@ -10587,6 +11023,21 @@ 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
@@ -10705,9 +11156,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);
@@ -10716,9 +11168,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);
@@ -10731,7 +11184,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;
 {
@@ -10815,15 +11268,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)
+static void
+dwarf2out_source_line (line, filename)
+     unsigned int line;
      register const char *filename;
-     register unsigned line;
 {
   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);
@@ -10843,9 +11301,6 @@ dwarf2out_line (filename, line)
          register 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
@@ -10872,9 +11327,6 @@ dwarf2out_line (filename, line)
 
          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)
@@ -10895,12 +11347,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)
+     register unsigned int lineno;
+     register const char *filename;
 {
   if (flag_eliminate_dwarf2_dups)
     {
@@ -10908,26 +11360,38 @@ 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)
+    {
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      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)
+    {
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      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;
@@ -10935,27 +11399,40 @@ dwarf2out_define (lineno, buffer)
   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)
+    {
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      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;
 {
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      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;
+static void
+dwarf2out_init (main_input_filename)
      register const char *main_input_filename;
 {
   init_file_table ();
@@ -11007,7 +11484,8 @@ dwarf2out_init (asm_out_file, main_input_filename)
   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
@@ -11016,8 +11494,10 @@ dwarf2out_init (asm_out_file, main_input_filename)
                               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 (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
+  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LOC_SECTION);
+  ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
+  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ABBREV_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
   if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
     {
@@ -11028,16 +11508,24 @@ dwarf2out_init (asm_out_file, main_input_filename)
   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);
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
+                                  DEBUG_MACINFO_SECTION_LABEL, 0);
+      ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
+    }
 }
 
 /* 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)
+     register 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
@@ -11096,31 +11584,31 @@ dwarf2out_finish ()
   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 ();
-       }
-
-      /* 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);
-       }
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+      output_line_info ();
+    }
 
-      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);
     }
 
-#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.  */
@@ -11129,13 +11617,13 @@ dwarf2out_finish ()
   output_comp_unit (comp_unit_die);
 
   /* Output the abbreviation table.  */
-  ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
+  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ABBREV_SECTION);
   output_abbrev_section ();
 
   if (pubname_table_in_use)
     {
       /* Output public names table.  */
-      ASM_OUTPUT_SECTION (asm_out_file, PUBNAMES_SECTION);
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION);
       output_pubnames ();
     }
 
@@ -11144,8 +11632,24 @@ dwarf2out_finish ()
   if (fde_table_in_use)
     {
       /* Output the address range information.  */
-      ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
       output_aranges ();
     }
+  /* Output location list section if necessary */
+  if (have_location_lists)
+    {
+      /* Output the location lists info. */
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LOC_SECTION);
+      output_location_lists (die);
+      have_location_lists = 0;
+    }
+
+  /* Have to end the primary source file. */
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    { 
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+    }
+  
 }
 #endif /* DWARF2_DEBUGGING_INFO */