OSDN Git Service

Fix problem that caused compiled java code to trigger an internal gdb error.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 5f75d29..cc3c9f4 100644 (file)
@@ -1,6 +1,6 @@
 /* Output Dwarf2 format symbol table information from GCC.
    Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004 Free Software Foundation, Inc.
+   2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
@@ -39,6 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "version.h"
 #include "flags.h"
 #include "real.h"
 #include "rtl.h"
@@ -65,6 +66,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "langhooks.h"
 #include "hashtab.h"
 #include "cgraph.h"
+#include "input.h"
 
 #ifdef DWARF2_DEBUGGING_INFO
 static void dwarf2out_source_line (unsigned int, const char *);
@@ -114,33 +116,38 @@ dwarf2out_do_frame (void)
 /* Various versions of targetm.eh_frame_section.  Note these must appear
    outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro guards.  */
 
-/* Version of targetm.eh_frame_section for systems with named sections.  */ 
+/* Version of targetm.eh_frame_section for systems with named sections.  */
 void
 named_section_eh_frame_section (void)
 {
 #ifdef EH_FRAME_SECTION_NAME
-#ifdef HAVE_LD_RO_RW_SECTION_MIXING
-  int fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
-  int per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
-  int lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
   int flags;
 
-  flags = (! flag_pic
-          || ((fde_encoding & 0x70) != DW_EH_PE_absptr
-              && (fde_encoding & 0x70) != DW_EH_PE_aligned
-              && (per_encoding & 0x70) != DW_EH_PE_absptr
-              && (per_encoding & 0x70) != DW_EH_PE_aligned
-              && (lsda_encoding & 0x70) != DW_EH_PE_absptr
-              && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
-         ? 0 : SECTION_WRITE;
+  if (EH_TABLES_CAN_BE_READ_ONLY)
+    {
+      int fde_encoding;
+      int per_encoding;
+      int lsda_encoding;
+
+      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);
+      flags = (! flag_pic
+              || ((fde_encoding & 0x70) != DW_EH_PE_absptr
+                  && (fde_encoding & 0x70) != DW_EH_PE_aligned
+                  && (per_encoding & 0x70) != DW_EH_PE_absptr
+                  && (per_encoding & 0x70) != DW_EH_PE_aligned
+                  && (lsda_encoding & 0x70) != DW_EH_PE_absptr
+                  && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
+             ? 0 : SECTION_WRITE;
+    }
+  else
+    flags = SECTION_WRITE;
   named_section_flags (EH_FRAME_SECTION_NAME, flags);
-#else
-  named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
-#endif
 #endif
 }
 
-/* Version of targetm.eh_frame_section for systems using collect2.  */ 
+/* Version of targetm.eh_frame_section for systems using collect2.  */
 void
 collect2_eh_frame_section (void)
 {
@@ -148,7 +155,7 @@ collect2_eh_frame_section (void)
 
   data_section ();
   ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
-  (*targetm.asm_out.globalize_label) (asm_out_file, IDENTIFIER_POINTER (label));
+  targetm.asm_out.globalize_label (asm_out_file, IDENTIFIER_POINTER (label));
   ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
 }
 
@@ -242,6 +249,7 @@ typedef struct cfa_loc GTY(())
 
 typedef struct dw_fde_struct GTY(())
 {
+  tree decl;
   const char *dw_fde_begin;
   const char *dw_fde_current_label;
   const char *dw_fde_end;
@@ -355,8 +363,7 @@ static void initial_return_save (rtx);
 static HOST_WIDE_INT stack_adjust_offset (rtx);
 static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
 static void output_call_frame_info (int);
-static void dwarf2out_stack_adjust (rtx);
-static void queue_reg_save (const char *, rtx, HOST_WIDE_INT);
+static void dwarf2out_stack_adjust (rtx, bool);
 static void flush_queued_reg_saves (void);
 static bool clobbers_queued_reg_save (rtx);
 static void dwarf2out_frame_debug_expr (rtx, const char *);
@@ -390,7 +397,9 @@ static void def_cfa_1 (const char *, dw_cfa_location *);
 #define FUNC_END_LABEL         "LFE"
 #endif
 
+#ifndef FRAME_BEGIN_LABEL
 #define FRAME_BEGIN_LABEL      "Lframe"
+#endif
 #define CIE_AFTER_SIZE_LABEL   "LSCIE"
 #define CIE_END_LABEL          "LECIE"
 #define FDE_LABEL              "LSFDE"
@@ -485,8 +494,7 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
       }
 
 #ifdef DWARF_ALT_FRAME_RETURN_COLUMN
-  if (! wrote_return_column)
-    abort ();
+  gcc_assert (wrote_return_column);
   i = DWARF_ALT_FRAME_RETURN_COLUMN;
   wrote_return_column = false;
 #else
@@ -808,9 +816,7 @@ reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT
 
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
 
-  /* The following comparison is correct. -1 is used to indicate that
-     the value isn't a register number.  */
-  if (sreg == (unsigned int) -1)
+  if (sreg == INVALID_REGNUM)
     {
       if (reg & ~0x3f)
        /* The register number won't fit in 6 bits, so we have to use
@@ -827,8 +833,7 @@ reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT
           description.  */
        HOST_WIDE_INT check_offset = offset / DWARF_CIE_DATA_ALIGNMENT;
 
-       if (check_offset * DWARF_CIE_DATA_ALIGNMENT != offset)
-         abort ();
+       gcc_assert (check_offset * DWARF_CIE_DATA_ALIGNMENT == offset);
       }
 #endif
       offset /= DWARF_CIE_DATA_ALIGNMENT;
@@ -838,8 +843,7 @@ reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT
       cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
     }
   else if (sreg == reg)
-    /* We could emit a DW_CFA_same_value in this case, but don't bother.  */
-    return;
+    cfi->dw_cfi_opc = DW_CFA_same_value;
   else
     {
       cfi->dw_cfi_opc = DW_CFA_register;
@@ -890,7 +894,7 @@ dwarf2out_args_size (const char *label, HOST_WIDE_INT size)
 void
 dwarf2out_reg_save (const char *label, unsigned int reg, HOST_WIDE_INT offset)
 {
-  reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
+  reg_save (label, DWARF_FRAME_REGNUM (reg), INVALID_REGNUM, offset);
 }
 
 /* Entry point for saving the return address in the stack.
@@ -899,7 +903,7 @@ dwarf2out_reg_save (const char *label, unsigned int reg, HOST_WIDE_INT offset)
 void
 dwarf2out_return_save (const char *label, HOST_WIDE_INT offset)
 {
-  reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset);
+  reg_save (label, DWARF_FRAME_RETURN_COLUMN, INVALID_REGNUM, offset);
 }
 
 /* Entry point for saving the return address in a register.
@@ -908,7 +912,7 @@ dwarf2out_return_save (const char *label, HOST_WIDE_INT offset)
 void
 dwarf2out_return_reg (const char *label, unsigned int sreg)
 {
-  reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0);
+  reg_save (label, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0);
 }
 
 /* Record the initial position of the return address.  RTL is
@@ -917,7 +921,7 @@ dwarf2out_return_reg (const char *label, unsigned int sreg)
 static void
 initial_return_save (rtx rtl)
 {
-  unsigned int reg = (unsigned int) -1;
+  unsigned int reg = INVALID_REGNUM;
   HOST_WIDE_INT offset = 0;
 
   switch (GET_CODE (rtl))
@@ -933,25 +937,22 @@ initial_return_save (rtx rtl)
       switch (GET_CODE (rtl))
        {
        case REG:
-         if (REGNO (rtl) != STACK_POINTER_REGNUM)
-           abort ();
+         gcc_assert (REGNO (rtl) == STACK_POINTER_REGNUM);
          offset = 0;
          break;
 
        case PLUS:
-         if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM)
-           abort ();
+         gcc_assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
          offset = INTVAL (XEXP (rtl, 1));
          break;
 
        case MINUS:
-         if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM)
-           abort ();
+         gcc_assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
          offset = -INTVAL (XEXP (rtl, 1));
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       break;
@@ -960,16 +961,16 @@ initial_return_save (rtx rtl)
       /* The return address is at some offset from any value we can
         actually load.  For instance, on the SPARC it is in %i7+8. Just
         ignore the offset for now; it doesn't matter for unwinding frames.  */
-      if (GET_CODE (XEXP (rtl, 1)) != CONST_INT)
-       abort ();
+      gcc_assert (GET_CODE (XEXP (rtl, 1)) == CONST_INT);
       initial_return_save (XEXP (rtl, 0));
       return;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
-  reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
+  if (reg != DWARF_FRAME_RETURN_COLUMN)
+    reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
 }
 
 /* Given a SET, calculate the amount of stack adjustment it
@@ -996,7 +997,7 @@ stack_adjust_offset (rtx pattern)
       if (code == PLUS)
        offset = -offset;
     }
-  else if (GET_CODE (dest) == MEM)
+  else if (MEM_P (dest))
     {
       /* (set (mem (pre_dec (reg sp))) (foo)) */
       src = XEXP (dest, 0);
@@ -1010,9 +1011,8 @@ stack_adjust_offset (rtx pattern)
            {
              rtx val = XEXP (XEXP (src, 1), 1);
              /* We handle only adjustments by constant amount.  */
-             if (GET_CODE (XEXP (src, 1)) != PLUS ||
-                 GET_CODE (val) != CONST_INT)
-               abort ();
+             gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS
+                         && GET_CODE (val) == CONST_INT);
              offset = -INTVAL (val);
              break;
            }
@@ -1051,33 +1051,44 @@ stack_adjust_offset (rtx pattern)
    much extra space it needs to pop off the stack.  */
 
 static void
-dwarf2out_stack_adjust (rtx insn)
+dwarf2out_stack_adjust (rtx insn, bool after_p)
 {
   HOST_WIDE_INT offset;
   const char *label;
   int i;
 
-  if (!flag_asynchronous_unwind_tables && GET_CODE (insn) == CALL_INSN)
-    {
-      /* Extract the size of the args from the CALL rtx itself.  */
-      insn = PATTERN (insn);
-      if (GET_CODE (insn) == PARALLEL)
-       insn = XVECEXP (insn, 0, 0);
-      if (GET_CODE (insn) == SET)
-       insn = SET_SRC (insn);
-      if (GET_CODE (insn) != CALL)
-       abort ();
-
-      dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
-      return;
-    }
+  /* Don't handle epilogues at all.  Certainly it would be wrong to do so
+     with this function.  Proper support would require all frame-related
+     insns to be marked, and to be able to handle saving state around
+     epilogues textually in the middle of the function.  */
+  if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
+    return;
 
   /* If only calls can throw, and we have a frame pointer,
      save up adjustments until we see the CALL_INSN.  */
-  else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
-    return;
+  if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
+    {
+      if (CALL_P (insn) && !after_p)
+       {
+         /* Extract the size of the args from the CALL rtx itself.  */
+         insn = PATTERN (insn);
+         if (GET_CODE (insn) == PARALLEL)
+           insn = XVECEXP (insn, 0, 0);
+         if (GET_CODE (insn) == SET)
+           insn = SET_SRC (insn);
+         gcc_assert (GET_CODE (insn) == CALL);
+         dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+       }
+      return;
+    }
 
-  if (GET_CODE (insn) == BARRIER)
+  if (CALL_P (insn) && !after_p)
+    {
+      if (!flag_asynchronous_unwind_tables)
+       dwarf2out_args_size ("", args_size);
+      return;
+    }
+  else if (BARRIER_P (insn))
     {
       /* When we see a BARRIER, we know to reset args_size to 0.  Usually
         the compiler will have already emitted a stack adjustment, but
@@ -1118,7 +1129,8 @@ dwarf2out_stack_adjust (rtx insn)
 
   label = dwarf2out_cfi_label ();
   def_cfa_1 (label, &cfa);
-  dwarf2out_args_size (label, args_size);
+  if (flag_asynchronous_unwind_tables)
+    dwarf2out_args_size (label, args_size);
 }
 
 #endif
@@ -1132,53 +1144,139 @@ struct queued_reg_save GTY(())
   struct queued_reg_save *next;
   rtx reg;
   HOST_WIDE_INT cfa_offset;
+  rtx saved_reg;
 };
 
 static GTY(()) struct queued_reg_save *queued_reg_saves;
 
+/* The caller's ORIG_REG is saved in SAVED_IN_REG.  */
+struct reg_saved_in_data GTY(()) {
+  rtx orig_reg;
+  rtx saved_in_reg;
+};
+
+/* A list of registers saved in other registers.
+   The list intentionally has a small maximum capacity of 4; if your
+   port needs more than that, you might consider implementing a
+   more efficient data structure.  */
+static GTY(()) struct reg_saved_in_data regs_saved_in_regs[4];
+static GTY(()) size_t num_regs_saved_in_regs;
+
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 static const char *last_reg_save_label;
 
+/* Add an entry to QUEUED_REG_SAVES saying that REG is now saved at
+   SREG, or if SREG is NULL then it is saved at OFFSET to the CFA.  */
+
 static void
-queue_reg_save (const char *label, rtx reg, HOST_WIDE_INT offset)
+queue_reg_save (const char *label, rtx reg, rtx sreg, HOST_WIDE_INT offset)
 {
-  struct queued_reg_save *q = ggc_alloc (sizeof (*q));
+  struct queued_reg_save *q;
+
+  /* Duplicates waste space, but it's also necessary to remove them
+     for correctness, since the queue gets output in reverse
+     order.  */
+  for (q = queued_reg_saves; q != NULL; q = q->next)
+    if (REGNO (q->reg) == REGNO (reg))
+      break;
+
+  if (q == NULL)
+    {
+      q = ggc_alloc (sizeof (*q));
+      q->next = queued_reg_saves;
+      queued_reg_saves = q;
+    }
 
-  q->next = queued_reg_saves;
   q->reg = reg;
   q->cfa_offset = offset;
-  queued_reg_saves = q;
+  q->saved_reg = sreg;
 
   last_reg_save_label = label;
 }
 
+/* Output all the entries in QUEUED_REG_SAVES.  */
+
 static void
 flush_queued_reg_saves (void)
 {
-  struct queued_reg_save *q, *next;
+  struct queued_reg_save *q;
 
-  for (q = queued_reg_saves; q; q = next)
+  for (q = queued_reg_saves; q; q = q->next)
     {
-      dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
-      next = q->next;
+      size_t i;
+      unsigned int reg, sreg;
+
+      for (i = 0; i < num_regs_saved_in_regs; i++)
+       if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (q->reg))
+         break;
+      if (q->saved_reg && i == num_regs_saved_in_regs)
+       {
+         gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
+         num_regs_saved_in_regs++;
+       }
+      if (i != num_regs_saved_in_regs)
+       {
+         regs_saved_in_regs[i].orig_reg = q->reg;
+         regs_saved_in_regs[i].saved_in_reg = q->saved_reg;
+       }
+
+      reg = DWARF_FRAME_REGNUM (REGNO (q->reg));
+      if (q->saved_reg)
+       sreg = DWARF_FRAME_REGNUM (REGNO (q->saved_reg));
+      else
+       sreg = INVALID_REGNUM;
+      reg_save (last_reg_save_label, reg, sreg, q->cfa_offset);
     }
 
   queued_reg_saves = NULL;
   last_reg_save_label = NULL;
 }
 
+/* Does INSN clobber any register which QUEUED_REG_SAVES lists a saved
+   location for?  Or, does it clobber a register which we've previously
+   said that some other register is saved in, and for which we now
+   have a new location for?  */
+
 static bool
 clobbers_queued_reg_save (rtx insn)
 {
   struct queued_reg_save *q;
 
   for (q = queued_reg_saves; q; q = q->next)
-    if (modified_in_p (q->reg, insn))
-      return true;
+    {
+      size_t i;
+      if (modified_in_p (q->reg, insn))
+       return true;
+      for (i = 0; i < num_regs_saved_in_regs; i++)
+       if (REGNO (q->reg) == REGNO (regs_saved_in_regs[i].orig_reg)
+           && modified_in_p (regs_saved_in_regs[i].saved_in_reg, insn))
+         return true;
+    }
 
   return false;
 }
 
+/* What register, if any, is currently saved in REG?  */
+
+static rtx
+reg_saved_in (rtx reg)
+{
+  unsigned int regn = REGNO (reg);
+  size_t i;
+  struct queued_reg_save *q;
+
+  for (q = queued_reg_saves; q; q = q->next)
+    if (q->saved_reg && regn == REGNO (q->saved_reg))
+      return q->reg;
+
+  for (i = 0; i < num_regs_saved_in_regs; i++)
+    if (regs_saved_in_regs[i].saved_in_reg
+       && regn == REGNO (regs_saved_in_regs[i].saved_in_reg))
+      return regs_saved_in_regs[i].orig_reg;
+
+  return NULL_RTX;
+}
+
 
 /* A temporary register holding an integral value used in adjusting SP
    or setting up the store_reg.  The "offset" field holds the integer
@@ -1187,8 +1285,8 @@ static dw_cfa_location cfa_temp;
 
 /* Record call frame debugging information for an expression EXPR,
    which either sets SP or FP (adjusting how we calculate the frame
-   address) or saves a register to the stack.  LABEL indicates the
-   address of EXPR.
+   address) or saves a register to the stack or another register.
+   LABEL indicates the address of EXPR.
 
    This function encodes a state machine mapping rtxes to actions on
    cfa, cfa_store, and cfa_temp.reg.  We describe these rules so
@@ -1212,12 +1310,20 @@ static dw_cfa_location cfa_temp;
   RTX_FRAME_RELATED_P is set on an insn which modifies memory, it's a
   register save, and the register used to calculate the destination
   had better be the one we think we're using for this purpose.
+  It's also assumed that a copy from a call-saved register to another
+  register is saving that register if RTX_FRAME_RELATED_P is set on
+  that instruction.  If the copy is from a call-saved register to
+  the *same* register, that means that the register is now the same
+  value as in the caller.
 
   Except: If the register being saved is the CFA register, and the
   offset is nonzero, we are saving the CFA, so we assume we have to
   use DW_CFA_def_cfa_expression.  If the offset is 0, we assume that
   the intent is to save the value of SP from the previous frame.
 
+  In addition, if a register has previously been saved to a different
+  register,
+
   Invariants / Summaries of Rules
 
   cfa         current rule for calculating the CFA.  It usually
@@ -1335,7 +1441,11 @@ static dw_cfa_location cfa_temp;
   (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)  */
+          cfa_temp.offset -= mode_size(mem)
+
+  Rule 15:
+  (set <reg> {unspec, unspec_volatile})
+  effects: target-dependent  */
 
 static void
 dwarf2out_frame_debug_expr (rtx expr, const char *label)
@@ -1362,35 +1472,49 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
       return;
     }
 
-  if (GET_CODE (expr) != SET)
-    abort ();
+  gcc_assert (GET_CODE (expr) == SET);
 
   src = SET_SRC (expr);
   dest = SET_DEST (expr);
 
+  if (GET_CODE (src) == REG)
+    {
+      rtx rsi = reg_saved_in (src);
+      if (rsi)
+       src = rsi;
+    }
+
   switch (GET_CODE (dest))
     {
     case REG:
-      /* Rule 1 */
-      /* Update the CFA rule wrt SP or FP.  Make sure src is
-        relative to the current CFA register.  */
       switch (GET_CODE (src))
        {
          /* Setting FP from SP.  */
        case REG:
          if (cfa.reg == (unsigned) REGNO (src))
-           /* OK.  */
-           ;
+           {
+             /* Rule 1 */
+             /* Update the CFA rule wrt SP or FP.  Make sure src is
+                relative to the current CFA register.
+
+                We used to require that dest be either SP or FP, but the
+                ARM copies SP to a temporary register, and from there to
+                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;
+           }
          else
-           abort ();
-
-         /* We used to require that dest be either SP or FP, but the
-            ARM copies SP to a temporary register, and from there to
-            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;
+           {
+             /* Saving a register in a register.  */
+             gcc_assert (call_used_regs [REGNO (dest)]
+                         && (!fixed_regs [REGNO (dest)]
+                             /* For the SPARC and its register window.  */
+                             || DWARF_FRAME_REGNUM (REGNO (src))
+                                  == DWARF_FRAME_RETURN_COLUMN));
+             queue_reg_save (label, src, dest, 0);
+           }
          break;
 
        case PLUS:
@@ -1406,26 +1530,25 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
                  offset = INTVAL (XEXP (src, 1));
                  break;
                case REG:
-                 if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp.reg)
-                   abort ();
+                 gcc_assert ((unsigned) REGNO (XEXP (src, 1))
+                             == cfa_temp.reg);
                  offset = cfa_temp.offset;
                  break;
                default:
-                 abort ();
+                 gcc_unreachable ();
                }
 
              if (XEXP (src, 0) == hard_frame_pointer_rtx)
                {
                  /* Restoring SP from FP in the epilogue.  */
-                 if (cfa.reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
-                   abort ();
+                 gcc_assert (cfa.reg == (unsigned) HARD_FRAME_POINTER_REGNUM);
                  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 ();
+             else
+               gcc_assert (XEXP (src, 0) == stack_pointer_rtx);
 
              if (GET_CODE (src) != MINUS)
                offset = -offset;
@@ -1439,29 +1562,23 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
              /* Rule 3 */
              /* Either setting the FP from an offset of the SP,
                 or adjusting the FP */
-             if (! frame_pointer_needed)
-               abort ();
+             gcc_assert (frame_pointer_needed);
 
-             if (GET_CODE (XEXP (src, 0)) == REG
-                 && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg
-                 && GET_CODE (XEXP (src, 1)) == CONST_INT)
-               {
-                 offset = INTVAL (XEXP (src, 1));
-                 if (GET_CODE (src) != MINUS)
-                   offset = -offset;
-                 cfa.offset += offset;
-                 cfa.reg = HARD_FRAME_POINTER_REGNUM;
-               }
-             else
-               abort ();
+             gcc_assert (REG_P (XEXP (src, 0))
+                         && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg
+                         && GET_CODE (XEXP (src, 1)) == CONST_INT);
+             offset = INTVAL (XEXP (src, 1));
+             if (GET_CODE (src) != MINUS)
+               offset = -offset;
+             cfa.offset += offset;
+             cfa.reg = HARD_FRAME_POINTER_REGNUM;
            }
          else
            {
-             if (GET_CODE (src) == MINUS)
-               abort ();
+             gcc_assert (GET_CODE (src) != MINUS);
 
              /* Rule 4 */
-             if (GET_CODE (XEXP (src, 0)) == REG
+             if (REG_P (XEXP (src, 0))
                  && REGNO (XEXP (src, 0)) == cfa.reg
                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
                {
@@ -1476,14 +1593,13 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
                }
 
              /* Rule 5 */
-             else if (GET_CODE (XEXP (src, 0)) == REG
+             else if (REG_P (XEXP (src, 0))
                       && 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 (cfa.reg != STACK_POINTER_REGNUM)
-                   abort ();
+                 gcc_assert (cfa.reg == STACK_POINTER_REGNUM);
                  cfa_store.reg = REGNO (dest);
                  cfa_store.offset = cfa.offset - cfa_temp.offset;
                }
@@ -1496,7 +1612,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
                  cfa_temp.offset = INTVAL (XEXP (src, 1));
                }
              else
-               abort ();
+               gcc_unreachable ();
            }
          break;
 
@@ -1508,10 +1624,9 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
 
          /* Rule 7 */
        case IOR:
-         if (GET_CODE (XEXP (src, 0)) != REG
-             || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg
-             || GET_CODE (XEXP (src, 1)) != CONST_INT)
-           abort ();
+         gcc_assert (REG_P (XEXP (src, 0))
+                     && (unsigned) REGNO (XEXP (src, 0)) == cfa_temp.reg
+                     && GET_CODE (XEXP (src, 1)) == CONST_INT);
 
          if ((unsigned) REGNO (dest) != cfa_temp.reg)
            cfa_temp.reg = REGNO (dest);
@@ -1524,16 +1639,22 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
        case HIGH:
          break;
 
+         /* Rule 15 */
+       case UNSPEC:
+       case UNSPEC_VOLATILE:
+         gcc_assert (targetm.dwarf_handle_frame_unspec);
+         targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
+         break;
+
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       def_cfa_1 (label, &cfa);
       break;
 
     case MEM:
-      if (GET_CODE (src) != REG)
-       abort ();
+      gcc_assert (REG_P (src));
 
       /* Saving a register to the stack.  Make sure dest is relative to the
         CFA register.  */
@@ -1543,13 +1664,12 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
          /* With a push.  */
        case PRE_MODIFY:
          /* We can't handle variable size modifications.  */
-         if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT)
-           abort ();
+         gcc_assert (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1))
+                     == CONST_INT);
          offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
 
-         if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
-             || cfa_store.reg != STACK_POINTER_REGNUM)
-           abort ();
+         gcc_assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM
+                     && cfa_store.reg == STACK_POINTER_REGNUM);
 
          cfa_store.offset += offset;
          if (cfa.reg == STACK_POINTER_REGNUM)
@@ -1565,9 +1685,8 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
          if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
            offset = -offset;
 
-         if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
-             || cfa_store.reg != STACK_POINTER_REGNUM)
-           abort ();
+         gcc_assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM
+                     && cfa_store.reg == STACK_POINTER_REGNUM);
 
          cfa_store.offset += offset;
          if (cfa.reg == STACK_POINTER_REGNUM)
@@ -1581,41 +1700,52 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
        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;
+         {
+           int regno;
 
-         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 ();
+           gcc_assert (GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
+           offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+           if (GET_CODE (XEXP (dest, 0)) == MINUS)
+             offset = -offset;
+
+           regno = REGNO (XEXP (XEXP (dest, 0), 0));
+
+           if (cfa_store.reg == (unsigned) regno)
+             offset -= cfa_store.offset;
+           else
+             {
+               gcc_assert (cfa_temp.reg == (unsigned) regno);
+               offset -= cfa_temp.offset;
+             }
+         }
          break;
 
          /* Rule 13 */
          /* Without an offset.  */
        case REG:
-         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 ();
+         {
+           int regno = REGNO (XEXP (dest, 0));
+
+           if (cfa_store.reg == (unsigned) regno)
+             offset = -cfa_store.offset;
+           else
+             {
+               gcc_assert (cfa_temp.reg == (unsigned) regno);
+               offset = -cfa_temp.offset;
+             }
+         }
          break;
 
          /* Rule 14 */
        case POST_INC:
-         if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
-           abort ();
+         gcc_assert (cfa_temp.reg
+                     == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)));
          offset = -cfa_temp.offset;
          cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       if (REGNO (src) != STACK_POINTER_REGNUM
@@ -1630,7 +1760,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
                 we're saving SP like any other register; this happens
                 on the ARM.  */
              def_cfa_1 (label, &cfa);
-             queue_reg_save (label, stack_pointer_rtx, offset);
+             queue_reg_save (label, stack_pointer_rtx, NULL_RTX, offset);
              break;
            }
          else
@@ -1639,10 +1769,9 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
                 calculate the CFA.  */
              rtx x = XEXP (dest, 0);
 
-             if (GET_CODE (x) != REG)
+             if (!REG_P (x))
                x = XEXP (x, 0);
-             if (GET_CODE (x) != REG)
-               abort ();
+             gcc_assert (REG_P (x));
 
              cfa.reg = REGNO (x);
              cfa.base_offset = offset;
@@ -1653,49 +1782,60 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
        }
 
       def_cfa_1 (label, &cfa);
-      queue_reg_save (label, src, offset);
+      queue_reg_save (label, src, NULL_RTX, offset);
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
 /* Record call frame debugging information for INSN, which either
    sets SP or FP (adjusting how we calculate the frame address) or saves a
-   register to the stack.  If INSN is NULL_RTX, initialize our state.  */
+   register to the stack.  If INSN is NULL_RTX, initialize our state.
+
+   If AFTER_P is false, we're being called before the insn is emitted,
+   otherwise after.  Call instructions get invoked twice.  */
 
 void
-dwarf2out_frame_debug (rtx insn)
+dwarf2out_frame_debug (rtx insn, bool after_p)
 {
   const char *label;
   rtx src;
 
   if (insn == NULL_RTX)
     {
+      size_t i;
+
       /* Flush any queued register saves.  */
       flush_queued_reg_saves ();
 
       /* Set up state for generating call frame debug info.  */
       lookup_cfa (&cfa);
-      if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
-       abort ();
+      gcc_assert (cfa.reg
+                 == (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
 
       cfa.reg = STACK_POINTER_REGNUM;
       cfa_store = cfa;
       cfa_temp.reg = -1;
       cfa_temp.offset = 0;
+
+      for (i = 0; i < num_regs_saved_in_regs; i++)
+       {
+         regs_saved_in_regs[i].orig_reg = NULL_RTX;
+         regs_saved_in_regs[i].saved_in_reg = NULL_RTX;
+       }
+      num_regs_saved_in_regs = 0;
       return;
     }
 
-  if (GET_CODE (insn) != INSN || clobbers_queued_reg_save (insn))
+  if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn))
     flush_queued_reg_saves ();
 
   if (! RTX_FRAME_RELATED_P (insn))
     {
       if (!ACCUMULATE_OUTGOING_ARGS)
-       dwarf2out_stack_adjust (insn);
-
+       dwarf2out_stack_adjust (insn, after_p);
       return;
     }
 
@@ -1753,7 +1893,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
       return dw_cfi_oprnd_loc;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1783,11 +1923,19 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
 
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
+/* Map register numbers held in the call frame info that gcc has
+   collected using DWARF_FRAME_REGNUM to those that should be output in
+   .debug_frame and .eh_frame.  */
+#ifndef DWARF2_FRAME_REG_OUT
+#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
+#endif
+
 /* Output a Call Frame Information opcode and its operand(s).  */
 
 static void
 output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
 {
+  unsigned long r;
   if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
     dw2_asm_output_data (1, (cfi->dw_cfi_opc
                             | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)),
@@ -1795,17 +1943,17 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
                         cfi->dw_cfi_oprnd1.dw_cfi_offset);
   else if (cfi->dw_cfi_opc == DW_CFA_offset)
     {
-      dw2_asm_output_data (1, (cfi->dw_cfi_opc
-                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)),
-                          "DW_CFA_offset, column 0x%lx",
-                          cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+      dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
+                          "DW_CFA_offset, column 0x%lx", r);
       dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
     }
   else if (cfi->dw_cfi_opc == DW_CFA_restore)
-    dw2_asm_output_data (1, (cfi->dw_cfi_opc
-                            | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)),
-                        "DW_CFA_restore, column 0x%lx",
-                        cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+    {
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+      dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
+                          "DW_CFA_restore, column 0x%lx", r);
+    }
   else
     {
       dw2_asm_output_data (1, cfi->dw_cfi_opc,
@@ -1850,15 +1998,15 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
 
        case DW_CFA_offset_extended:
        case DW_CFA_def_cfa:
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
-                                      NULL);
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
          break;
 
        case DW_CFA_offset_extended_sf:
        case DW_CFA_def_cfa_sf:
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
-                                      NULL);
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
          dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
          break;
 
@@ -1866,15 +2014,15 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
        case DW_CFA_undefined:
        case DW_CFA_same_value:
        case DW_CFA_def_cfa_register:
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
-                                      NULL);
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
          break;
 
        case DW_CFA_register:
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
-                                      NULL);
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num,
-                                      NULL);
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
          break;
 
        case DW_CFA_def_cfa_offset:
@@ -1896,7 +2044,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
 
        case DW_CFA_GNU_negative_offset_extended:
          /* Obsoleted by DW_CFA_offset_extended_sf.  */
-         abort ();
+         gcc_unreachable ();
 
        default:
          break;
@@ -1904,7 +2052,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
     }
 }
 
-/* Output the call frame information used to used to record information
+/* Output the call frame information used to record information
    that relates to calculating the frame pointer, and records the
    location of saved registers.  */
 
@@ -1926,6 +2074,22 @@ output_call_frame_info (int for_eh)
   if (fde_table_in_use == 0)
     return;
 
+  /* If we make FDEs linkonce, we may have to emit an empty label for
+     an FDE that wouldn't otherwise be emitted.  We want to avoid
+     having an FDE kept around when the function it refers to is
+     discarded.  Example where this matters: a primary function
+     template in C++ requires EH information, but an explicit
+     specialization doesn't.  */
+  if (TARGET_USES_WEAK_UNWIND_INFO
+      && ! flag_asynchronous_unwind_tables
+      && for_eh)
+    for (i = 0; i < fde_table_in_use; i++)
+      if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
+          && !fde_table[i].uses_eh_lsda
+         && ! DECL_WEAK (fde_table[i].decl))
+       targetm.asm_out.unwind_label (asm_out_file, fde_table[i].decl,
+                                     for_eh, /* empty */ 1);
+
   /* If we don't have any functions we'll want to unwind out of, don't
      emit any EH unwind information.  Note that if exceptions aren't
      enabled, we won't have collected nothrow information, and if we
@@ -1937,6 +2101,8 @@ output_call_frame_info (int for_eh)
       for (i = 0; i < fde_table_in_use; i++)
        if (fde_table[i].uses_eh_lsda)
          any_eh_needed = any_lsda_needed = true;
+        else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
+         any_eh_needed = true;
        else if (! fde_table[i].nothrow
                 && ! fde_table[i].all_throwers_are_sibcalls)
          any_eh_needed = true;
@@ -1950,7 +2116,7 @@ output_call_frame_info (int for_eh)
     app_enable ();
 
   if (for_eh)
-    (*targetm.asm_out.eh_frame_section) ();
+    targetm.asm_out.eh_frame_section ();
   else
     named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG);
 
@@ -2032,8 +2198,7 @@ output_call_frame_info (int for_eh)
 
          /* 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 ();
+         gcc_assert (size_of_uleb128 (augmentation_size) == 1);
        }
     }
 
@@ -2041,7 +2206,11 @@ output_call_frame_info (int for_eh)
   dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor");
   dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT,
                               "CIE Data Alignment Factor");
-  dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
+
+  if (DW_CIE_VERSION == 1)
+    dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
+  else
+    dw2_asm_output_data_uleb128 (DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
 
   if (augmentation[0])
     {
@@ -2079,10 +2248,12 @@ output_call_frame_info (int for_eh)
       /* Don't emit EH unwind info for leaf functions that don't need it.  */
       if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
          && (fde->nothrow || fde->all_throwers_are_sibcalls)
+         && ! (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
          && !fde->uses_eh_lsda)
        continue;
 
-      (*targetm.asm_out.internal_label) (asm_out_file, FDE_LABEL, for_eh + i * 2);
+      targetm.asm_out.unwind_label (asm_out_file, fde->decl, for_eh, /* empty */ 0);
+      targetm.asm_out.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);
       dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
@@ -2097,9 +2268,11 @@ output_call_frame_info (int for_eh)
 
       if (for_eh)
        {
+         rtx sym_ref = gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin);
+         SYMBOL_REF_FLAGS (sym_ref) |= SYMBOL_FLAG_LOCAL;
          dw2_asm_output_encoded_addr_rtx (fde_encoding,
-                  gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
-                  "FDE initial location");
+                                          sym_ref,
+                                          "FDE initial location");
          dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
                                fde->dw_fde_end, fde->dw_fde_begin,
                                "FDE address range");
@@ -2128,8 +2301,7 @@ output_call_frame_info (int for_eh)
                  int pad = -offset & (PTR_SIZE - 1);
 
                  size += pad;
-                 if (size_of_uleb128 (size) != 1)
-                   abort ();
+                 gcc_assert (size_of_uleb128 (size) == 1);
                }
 
              dw2_asm_output_data_uleb128 (size, "Augmentation size");
@@ -2188,11 +2360,12 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
                          const char *file ATTRIBUTE_UNUSED)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
+  char * dup_label;
   dw_fde_ref fde;
 
-  current_function_func_begin_label = 0;
+  current_function_func_begin_label = NULL;
 
-#ifdef IA64_UNWIND_INFO
+#ifdef TARGET_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.  */
@@ -2209,9 +2382,10 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
                               current_function_funcdef_no);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
                          current_function_funcdef_no);
-  current_function_func_begin_label = get_identifier (label);
+  dup_label = xstrdup (label);
+  current_function_func_begin_label = dup_label;
 
-#ifdef IA64_UNWIND_INFO
+#ifdef TARGET_UNWIND_INFO
   /* We can elide the fde allocation if we're not emitting debug info.  */
   if (! dwarf2out_do_frame ())
     return;
@@ -2232,12 +2406,13 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
 
   /* Add the new FDE at the end of the fde_table.  */
   fde = &fde_table[fde_table_in_use++];
-  fde->dw_fde_begin = xstrdup (label);
+  fde->decl = current_function_decl;
+  fde->dw_fde_begin = dup_label;
   fde->dw_fde_current_label = NULL;
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
   fde->funcdef_number = current_function_funcdef_no;
-  fde->nothrow = current_function_nothrow;
+  fde->nothrow = TREE_NOTHROW (current_function_decl);
   fde->uses_eh_lsda = cfun->uses_eh_lsda;
   fde->all_throwers_are_sibcalls = cfun->all_throwers_are_sibcalls;
 
@@ -2296,8 +2471,11 @@ dwarf2out_frame_finish (void)
   if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
     output_call_frame_info (0);
 
+#ifndef TARGET_UNWIND_INFO
+  /* Output another copy for the unwinder.  */
   if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
     output_call_frame_info (1);
+#endif
 }
 #endif
 \f
@@ -2328,7 +2506,7 @@ enum dw_val_class
   dw_val_class_const,
   dw_val_class_unsigned_const,
   dw_val_class_long_long,
-  dw_val_class_float,
+  dw_val_class_vec,
   dw_val_class_flag,
   dw_val_class_die_ref,
   dw_val_class_fde_ref,
@@ -2347,14 +2525,15 @@ typedef struct dw_long_long_struct GTY(())
 }
 dw_long_long_const;
 
-/* Describe a floating point constant value.  */
+/* Describe a floating point constant value, or a vector constant value.  */
 
-typedef struct dw_fp_struct GTY(())
+typedef struct dw_vec_struct GTY(())
 {
-  long * GTY((length ("%h.length"))) array;
+  unsigned char * GTY((length ("%h.length"))) array;
   unsigned length;
+  unsigned elt_size;
 }
-dw_float_const;
+dw_vec_const;
 
 /* The dw_val_node describes an attribute's value, as it is
    represented internally.  */
@@ -2368,10 +2547,10 @@ typedef struct dw_val_struct GTY(())
       unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset;
       dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
       dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
-      HOST_WIDE_INT GTY ((default (""))) val_int;
+      HOST_WIDE_INT GTY ((default)) val_int;
       unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
       dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long;
-      dw_float_const GTY ((tag ("dw_val_class_float"))) val_float;
+      dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
       struct dw_val_die_union
        {
          dw_die_ref die;
@@ -2923,8 +3102,7 @@ output_loc_operands (dw_loc_descr_ref loc)
       break;
     case DW_OP_const8u:
     case DW_OP_const8s:
-      if (HOST_BITS_PER_LONG < 64)
-       abort ();
+      gcc_assert (HOST_BITS_PER_LONG >= 64);
       dw2_asm_output_data (8, val1->v.val_int, NULL);
       break;
     case DW_OP_skip:
@@ -2932,10 +3110,8 @@ output_loc_operands (dw_loc_descr_ref loc)
       {
        int offset;
 
-       if (val1->val_class == dw_val_class_loc)
-         offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
-       else
-         abort ();
+       gcc_assert (val1->val_class == dw_val_class_loc);
+       offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
 
        dw2_asm_output_data (2, offset, NULL);
       }
@@ -2954,7 +3130,7 @@ output_loc_operands (dw_loc_descr_ref loc)
         aligned properly like we do for the main unwind info, so
         don't support emitting things larger than a byte if we're
         only doing unwinding.  */
-      abort ();
+      gcc_unreachable ();
 #endif
     case DW_OP_const1u:
     case DW_OP_const1s:
@@ -3030,7 +3206,7 @@ output_loc_operands (dw_loc_descr_ref loc)
                               val1->v.val_addr);
       fputc ('\n', asm_out_file);
 #else
-      abort ();
+      gcc_unreachable ();
 #endif
       break;
 
@@ -3082,8 +3258,7 @@ build_cfa_loc (dw_cfa_location *cfa)
 {
   struct dw_loc_descr_struct *head, *tmp;
 
-  if (cfa->indirect == 0)
-    abort ();
+  gcc_assert (cfa->indirect);
 
   if (cfa->base_offset)
     {
@@ -3233,7 +3408,11 @@ static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (tree);
 static void dwarf2out_global_decl (tree);
+static void dwarf2out_type_decl (tree, int);
+static void dwarf2out_imported_module_or_decl (tree, tree);
 static void dwarf2out_abstract_function (tree);
+static void dwarf2out_var_location (rtx);
+static void dwarf2out_begin_function (tree);
 
 /* The debug hooks structure.  */
 
@@ -3252,17 +3431,20 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_begin_prologue,
   debug_nothing_int_charstar,  /* end_prologue */
   dwarf2out_end_epilogue,
-  debug_nothing_tree,          /* begin_function */
+  dwarf2out_begin_function,
   debug_nothing_int,           /* end_function */
   dwarf2out_decl,              /* function_decl */
   dwarf2out_global_decl,
+  dwarf2out_type_decl,         /* type_decl */
+  dwarf2out_imported_module_or_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 */
-  debug_nothing_int            /* handle_pch */
+  debug_nothing_int,           /* handle_pch */
+  dwarf2out_var_location
 };
 #endif
 \f
@@ -3336,6 +3518,7 @@ typedef struct die_struct GTY(())
   dw_offset die_offset;
   unsigned long die_abbrev;
   int die_mark;
+  unsigned int decl_id;
 }
 die_node;
 
@@ -3453,20 +3636,35 @@ static GTY(()) varray_type file_table;
 static GTY(()) varray_type file_table_emitted;
 static GTY(()) size_t file_table_last_lookup_index;
 
-/* A pointer to the base of a table of references to DIE's that describe
-   declarations.  The table is indexed by DECL_UID() which is a unique
-   number identifying each decl.  */
-static GTY((length ("decl_die_table_allocated"))) dw_die_ref *decl_die_table;
+/* A hash table of references to DIE's that describe declarations.
+   The key is a DECL_UID() which is a unique number identifying each decl.  */
+static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
 
-/* Number of elements currently allocated for the decl_die_table.  */
-static GTY(()) unsigned decl_die_table_allocated;
+/* Node of the variable location list.  */
+struct var_loc_node GTY ((chain_next ("%h.next")))
+{
+  rtx GTY (()) var_loc_note;
+  const char * GTY (()) label;
+  struct var_loc_node * GTY (()) next;
+};
 
-/* Number of elements in decl_die_table currently in use.  */
-static GTY(()) unsigned decl_die_table_in_use;
+/* Variable location list.  */
+struct var_loc_list_def GTY (())
+{
+  struct var_loc_node * GTY (()) first;
 
-/* Size (in elements) of increments by which we may expand the
-   decl_die_table.  */
-#define DECL_DIE_TABLE_INCREMENT 256
+  /* Do not mark the last element of the chained list because
+     it is marked through the chain.  */
+  struct var_loc_node * GTY ((skip ("%h"))) last;
+
+  /* DECL_UID of the variable decl.  */
+  unsigned int decl_id;
+};
+typedef struct var_loc_list_def var_loc_list;
+
+
+/* Table of decl location linked lists.  */
+static GTY ((param_is (var_loc_list))) htab_t decl_loc_table;
 
 /* A pointer to the base of a list of references to DIE's that
    are uniquely identified by their tag, presence/absence of
@@ -3553,6 +3751,9 @@ static GTY(()) unsigned ranges_table_in_use;
 /* Whether we have location lists that need outputting */
 static GTY(()) unsigned have_location_lists;
 
+/* Unique label counter.  */
+static GTY(()) unsigned int loclabel_num;
+
 #ifdef DWARF2_DEBUGGING_INFO
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
@@ -3593,7 +3794,8 @@ static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WID
 static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_ref);
 static void add_AT_long_long (dw_die_ref, enum dwarf_attribute, unsigned long,
                              unsigned long);
-static void add_AT_float (dw_die_ref, enum dwarf_attribute, unsigned, long *);
+static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int,
+                              unsigned int, unsigned char *);
 static hashval_t debug_str_do_hash (const void *);
 static int debug_str_eq (const void *, const void *);
 static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *);
@@ -3632,14 +3834,21 @@ static bool is_java (void);
 static bool is_fortran (void);
 static bool is_ada (void);
 static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
 static inline void free_die (dw_die_ref);
 static void remove_children (dw_die_ref);
 static void add_child_die (dw_die_ref, dw_die_ref);
 static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
 static dw_die_ref lookup_type_die (tree);
 static void equate_type_number_to_die (tree, dw_die_ref);
+static hashval_t decl_die_table_hash (const void *);
+static int decl_die_table_eq (const void *, const void *);
 static dw_die_ref lookup_decl_die (tree);
+static hashval_t decl_loc_table_hash (const void *);
+static int decl_loc_table_eq (const void *, const void *);
+static var_loc_list *lookup_decl_loc (tree);
 static void equate_decl_number_to_die (tree, dw_die_ref);
+static void add_var_loc_to_decl (tree, struct var_loc_node *);
 static void print_spaces (FILE *);
 static void print_die (dw_die_ref, FILE *);
 static void print_dwarf_line_table (FILE *);
@@ -3696,21 +3905,22 @@ static void output_file_names (void);
 static dw_die_ref base_type_die (tree);
 static tree root_type (tree);
 static int is_base_type (tree);
-static bool is_ada_subrange_type (tree);
+static bool is_subrange_type (tree);
 static dw_die_ref subrange_type_die (tree, dw_die_ref);
 static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
 static int type_is_enum (tree);
-static unsigned int reg_number (rtx);
+static unsigned int dbx_reg_number (rtx);
 static dw_loc_descr_ref reg_loc_descriptor (rtx);
 static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
 static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
 static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
-static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT);
+static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT, bool);
 static int is_based_loc (rtx);
-static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode);
+static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool);
 static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
-static dw_loc_descr_ref loc_descriptor (rtx);
-static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
+static dw_loc_descr_ref loc_descriptor (rtx, bool);
+static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
+static dw_loc_descr_ref loc_descriptor_from_tree (tree);
 static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
 static tree field_type (tree);
 static unsigned int simple_type_align_in_bits (tree);
@@ -3721,8 +3931,12 @@ static void add_AT_location_description  (dw_die_ref, enum dwarf_attribute,
                                         dw_loc_descr_ref);
 static void add_data_member_location_attribute (dw_die_ref, tree);
 static void add_const_value_attribute (dw_die_ref, rtx);
+static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
+static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
+static void insert_float (rtx, unsigned char *);
 static rtx rtl_for_decl_location (tree);
-static void add_location_or_const_value_attribute (dw_die_ref, tree);
+static void add_location_or_const_value_attribute (dw_die_ref, tree,
+                                                  enum dwarf_attribute);
 static void tree_add_const_value_attribute (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_comp_dir_attribute (dw_die_ref);
@@ -3742,13 +3956,13 @@ static dw_die_ref scope_die_for (tree, dw_die_ref);
 static inline int local_scope_p (dw_die_ref);
 static inline int class_or_namespace_scope_p (dw_die_ref);
 static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
+static void add_calling_convention_attribute (dw_die_ref, tree);
 static const char *type_tag (tree);
 static tree member_declared_type (tree);
 #if 0
 static const char *decl_start_label (tree);
 #endif
 static void gen_array_type_die (tree, dw_die_ref);
-static void gen_set_type_die (tree, dw_die_ref);
 #if 0
 static void gen_entry_point_die (tree, dw_die_ref);
 #endif
@@ -3780,7 +3994,8 @@ static void decls_for_scope (tree, dw_die_ref, int);
 static int is_redundant_typedef (tree);
 static void gen_namespace_die (tree);
 static void gen_decl_die (tree, dw_die_ref);
-static dw_die_ref force_namespace_die (tree);
+static dw_die_ref force_decl_die (tree);
+static dw_die_ref force_type_die (tree);
 static dw_die_ref setup_namespace_context (tree, dw_die_ref);
 static void declare_in_namespace (tree, dw_die_ref);
 static unsigned lookup_filename (const char *);
@@ -3902,7 +4117,7 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 #endif
 \f
 /* We allow a language front-end to designate a function that is to be
-   called to "demangle" any name before it it put into a DIE.  */
+   called to "demangle" any name before it is put into a DIE.  */
 
 static const char *(*demangle_name_func) (const char *);
 
@@ -3917,7 +4132,7 @@ dwarf2out_set_demangle_name_func (const char *(*func) (const char *))
 static inline int
 is_pseudo_reg (rtx rtl)
 {
-  return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
+  return ((REG_P (rtl) && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
          || (GET_CODE (rtl) == SUBREG
              && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER));
 }
@@ -4058,6 +4273,8 @@ dwarf_tag_name (unsigned int tag)
       return "DW_TAG_variable";
     case DW_TAG_volatile_type:
       return "DW_TAG_volatile_type";
+    case DW_TAG_imported_module:
+      return "DW_TAG_imported_module";
     case DW_TAG_MIPS_loop:
       return "DW_TAG_MIPS_loop";
     case DW_TAG_format_label:
@@ -4377,12 +4594,9 @@ decl_ultimate_origin (tree decl)
   if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl)
     return NULL_TREE;
 
-#ifdef ENABLE_CHECKING
-  if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
-    /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
-       most distant ancestor, this should never happen.  */
-    abort ();
-#endif
+  /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+     most distant ancestor, this should never happen.  */
+  gcc_assert (!DECL_FROM_INLINE (DECL_ORIGIN (decl)));
 
   return DECL_ABSTRACT_ORIGIN (decl);
 }
@@ -4418,6 +4632,15 @@ block_ultimate_origin (tree block)
                       ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL);
        }
       while (lookahead != NULL && lookahead != ret_val);
+      
+      /* The block's abstract origin chain may not be the *ultimate* origin of
+        the block. It could lead to a DECL that has an abstract origin set.
+        If so, we want that DECL's abstract origin (which is what DECL_ORIGIN
+        will give us if it has one).  Note that DECL's abstract origins are
+        supposed to be the most distant ancestor (or so decl_ultimate_origin
+        claims), so we don't need to loop following the DECL origins.  */
+      if (DECL_P (ret_val))
+       return DECL_ORIGIN (ret_val);
 
       return ret_val;
     }
@@ -4480,10 +4703,8 @@ add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag)
 static inline unsigned
 AT_flag (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_flag)
-    return a->dw_attr_val.v.val_flag;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_flag);
+  return a->dw_attr_val.v.val_flag;
 }
 
 /* Add a signed integer attribute value to a DIE.  */
@@ -4503,10 +4724,8 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va
 static inline HOST_WIDE_INT
 AT_int (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_const)
-    return a->dw_attr_val.v.val_int;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_const);
+  return a->dw_attr_val.v.val_int;
 }
 
 /* Add an unsigned integer attribute value to a DIE.  */
@@ -4527,10 +4746,8 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
 static inline unsigned HOST_WIDE_INT
 AT_unsigned (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_unsigned_const)
-    return a->dw_attr_val.v.val_unsigned;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const);
+  return a->dw_attr_val.v.val_unsigned;
 }
 
 /* Add an unsigned double integer attribute value to a DIE.  */
@@ -4552,16 +4769,17 @@ add_AT_long_long (dw_die_ref die, enum dwarf_attribute attr_kind,
 /* Add a floating point attribute value to a DIE and return it.  */
 
 static inline void
-add_AT_float (dw_die_ref die, enum dwarf_attribute attr_kind,
-             unsigned int length, long int *array)
+add_AT_vec (dw_die_ref die, enum dwarf_attribute attr_kind,
+           unsigned int length, unsigned int elt_size, unsigned char *array)
 {
   dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
-  attr->dw_attr_val.val_class = dw_val_class_float;
-  attr->dw_attr_val.v.val_float.length = length;
-  attr->dw_attr_val.v.val_float.array = array;
+  attr->dw_attr_val.val_class = dw_val_class_vec;
+  attr->dw_attr_val.v.val_vec.length = length;
+  attr->dw_attr_val.v.val_vec.elt_size = elt_size;
+  attr->dw_attr_val.v.val_vec.array = array;
   add_dwarf_attr (die, attr);
 }
 
@@ -4611,10 +4829,8 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
 static inline const char *
 AT_string (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_str)
-    return a->dw_attr_val.v.val_str->str;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_str);
+  return a->dw_attr_val.v.val_str->str;
 }
 
 /* Find out whether a string should be output inline in DIE
@@ -4623,38 +4839,35 @@ AT_string (dw_attr_ref a)
 static int
 AT_string_form (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_str)
-    {
-      struct indirect_string_node *node;
-      unsigned int len;
-      char label[32];
+  struct indirect_string_node *node;
+  unsigned int len;
+  char label[32];
 
-      node = a->dw_attr_val.v.val_str;
-      if (node->form)
-       return node->form;
+  gcc_assert (a && AT_class (a) == dw_val_class_str);
 
-      len = strlen (node->str) + 1;
+  node = a->dw_attr_val.v.val_str;
+  if (node->form)
+    return node->form;
 
-      /* 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;
+  len = strlen (node->str) + 1;
 
-      /* 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 ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0
-         && (len - DWARF_OFFSET_SIZE) * node->refcount <= len)
-       return node->form = DW_FORM_string;
+  /* 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;
 
-      ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
-      ++dw2_string_counter;
-      node->label = xstrdup (label);
+  /* 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 ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0
+      && (len - DWARF_OFFSET_SIZE) * node->refcount <= len)
+    return node->form = DW_FORM_string;
 
-      return node->form = DW_FORM_strp;
-    }
+  ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+  ++dw2_string_counter;
+  node->label = xstrdup (label);
 
-  abort ();
+  return node->form = DW_FORM_strp;
 }
 
 /* Add a DIE reference attribute value to a DIE.  */
@@ -4679,18 +4892,15 @@ static inline void
 add_AT_specification (dw_die_ref die, dw_die_ref targ_die)
 {
   add_AT_die_ref (die, DW_AT_specification, targ_die);
-  if (targ_die->die_definition)
-    abort ();
+  gcc_assert (!targ_die->die_definition);
   targ_die->die_definition = die;
 }
 
 static inline dw_die_ref
 AT_ref (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_die_ref)
-    return a->dw_attr_val.v.val_die_ref.die;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
+  return a->dw_attr_val.v.val_die_ref.die;
 }
 
 static inline int
@@ -4705,10 +4915,8 @@ AT_ref_external (dw_attr_ref a)
 static inline void
 set_AT_ref_external (dw_attr_ref a, int i)
 {
-  if (a && AT_class (a) == dw_val_class_die_ref)
-    a->dw_attr_val.v.val_die_ref.external = i;
-  else
-    abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
+  a->dw_attr_val.v.val_die_ref.external = i;
 }
 
 /* Add an FDE reference attribute value to a DIE.  */
@@ -4742,10 +4950,8 @@ add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc
 static inline dw_loc_descr_ref
 AT_loc (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_loc)
-    return a->dw_attr_val.v.val_loc;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_loc);
+  return a->dw_attr_val.v.val_loc;
 }
 
 static inline void
@@ -4764,10 +4970,8 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
 static inline dw_loc_list_ref
 AT_loc_list (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_loc_list)
-    return a->dw_attr_val.v.val_loc_list;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
+  return a->dw_attr_val.v.val_loc_list;
 }
 
 /* Add an address constant attribute value to a DIE.  */
@@ -4787,10 +4991,8 @@ add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr)
 static inline rtx
 AT_addr (dw_attr_ref a)
 {
-  if (a && AT_class (a) == dw_val_class_addr)
-    return a->dw_attr_val.v.val_addr;
-
-  abort ();
+  gcc_assert (a && AT_class (a) == dw_val_class_addr);
+  return a->dw_attr_val.v.val_addr;
 }
 
 /* Add a label identifier attribute value to a DIE.  */
@@ -4854,16 +5056,14 @@ add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
 static inline const char *
 AT_lbl (dw_attr_ref a)
 {
-  if (a && (AT_class (a) == dw_val_class_lbl_id
-           || AT_class (a) == dw_val_class_lbl_offset))
-    return a->dw_attr_val.v.val_lbl_id;
-
-  abort ();
+  gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
+                   || AT_class (a) == dw_val_class_lbl_offset));
+  return a->dw_attr_val.v.val_lbl_id;
 }
 
 /* Get the attribute of type attr_kind.  */
 
-static inline dw_attr_ref
+static dw_attr_ref
 get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a;
@@ -4977,7 +5177,9 @@ is_fortran (void)
 {
   unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
-  return lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90;
+  return (lang == DW_LANG_Fortran77
+         || lang == DW_LANG_Fortran90
+         || lang == DW_LANG_Fortran95);
 }
 
 /* Return TRUE if the language is Java.  */
@@ -5034,6 +5236,34 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
     }
 }
 
+/* Remove child die whose die_tag is specified tag.  */
+
+static void
+remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
+{
+  dw_die_ref current, prev, next;
+  current = die->die_child;
+  prev = NULL;
+  while (current != NULL)
+    {
+      if (current->die_tag == tag)
+       {
+         next = current->die_sib;
+         if (prev == NULL)
+           die->die_child = next;
+         else
+           prev->die_sib = next;
+         free_die (current);
+         current = next;
+       }
+      else
+       {
+         prev = current;
+         current = current->die_sib;
+       }
+    }
+}
+
 /* Free up the memory used by DIE.  */
 
 static inline void
@@ -5078,8 +5308,7 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 {
   if (die != NULL && child_die != NULL)
     {
-      if (die == child_die)
-       abort ();
+      gcc_assert (die != child_die);
 
       child_die->die_parent = die;
       child_die->die_sib = die->die_child;
@@ -5105,9 +5334,9 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
        child = tmp;
     }
 
-  if (child->die_parent != parent
-      && child->die_parent != get_AT_ref (parent, DW_AT_specification))
-    abort ();
+  gcc_assert (child->die_parent == parent
+             || (child->die_parent
+                 == get_AT_ref (parent, DW_AT_specification)));
 
   for (p = &(child->die_parent->die_child); *p; p = &((*p)->die_sib))
     if (*p == child)
@@ -5162,14 +5391,53 @@ equate_type_number_to_die (tree type, dw_die_ref type_die)
   TYPE_SYMTAB_DIE (type) = type_die;
 }
 
+/* Returns a hash value for X (which really is a die_struct).  */
+
+static hashval_t
+decl_die_table_hash (const void *x)
+{
+  return (hashval_t) ((const dw_die_ref) x)->decl_id;
+}
+
+/* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
+
+static int
+decl_die_table_eq (const void *x, const void *y)
+{
+  return (((const dw_die_ref) x)->decl_id == DECL_UID ((const tree) y));
+}
+
 /* Return the DIE associated with a given declaration.  */
 
 static inline dw_die_ref
 lookup_decl_die (tree decl)
 {
-  unsigned decl_id = DECL_UID (decl);
+  return htab_find_with_hash (decl_die_table, decl, DECL_UID (decl));
+}
+
+/* Returns a hash value for X (which really is a var_loc_list).  */
+
+static hashval_t
+decl_loc_table_hash (const void *x)
+{
+  return (hashval_t) ((const var_loc_list *) x)->decl_id;
+}
+
+/* Return nonzero if decl_id of var_loc_list X is the same as
+   UID of decl *Y.  */
+
+static int
+decl_loc_table_eq (const void *x, const void *y)
+{
+  return (((const var_loc_list *) x)->decl_id == DECL_UID ((const tree) y));
+}
 
-  return (decl_id < decl_die_table_in_use ? decl_die_table[decl_id] : NULL);
+/* Return the var_loc list associated with a given declaration.  */
+
+static inline var_loc_list *
+lookup_decl_loc (tree decl)
+{
+  return htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
 }
 
 /* Equate a DIE to a particular declaration.  */
@@ -5178,27 +5446,50 @@ static void
 equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
 {
   unsigned int decl_id = DECL_UID (decl);
-  unsigned int num_allocated;
+  void **slot;
 
-  if (decl_id >= decl_die_table_allocated)
-    {
-      num_allocated
-       = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1)
-          / DECL_DIE_TABLE_INCREMENT)
-         * DECL_DIE_TABLE_INCREMENT;
+  slot = htab_find_slot_with_hash (decl_die_table, decl, decl_id, INSERT);
+  *slot = decl_die;
+  decl_die->decl_id = decl_id;
+}
 
-      decl_die_table = ggc_realloc (decl_die_table,
-                                   sizeof (dw_die_ref) * num_allocated);
+/* Add a variable location node to the linked list for DECL.  */
 
-      memset (&decl_die_table[decl_die_table_allocated], 0,
-            (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
-      decl_die_table_allocated = num_allocated;
-    }
+static void
+add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
+{
+  unsigned int decl_id = DECL_UID (decl);
+  var_loc_list *temp;
+  void **slot;
 
-  if (decl_id >= decl_die_table_in_use)
-    decl_die_table_in_use = (decl_id + 1);
+  slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
+  if (*slot == NULL)
+    {
+      temp = ggc_alloc_cleared (sizeof (var_loc_list));
+      temp->decl_id = decl_id;
+      *slot = temp;
+    }
+  else
+    temp = *slot;
 
-  decl_die_table[decl_id] = decl_die;
+  if (temp->last)
+    {
+      /* If the current location is the same as the end of the list,
+        we have nothing to do.  */
+      if (!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
+                       NOTE_VAR_LOCATION_LOC (loc->var_loc_note)))
+       {
+         /* Add LOC to the end of list and update LAST.  */
+         temp->last->next = loc;
+         temp->last = loc;
+       }
+    }
+  /* Do not add empty location to the beginning of the list.  */
+  else if (NOTE_VAR_LOCATION_LOC (loc->var_loc_note) != NULL_RTX)
+    {
+      temp->first = loc;
+      temp->last = loc;
+    }
 }
 \f
 /* Keep track of the number of spaces used to indent the
@@ -5264,8 +5555,8 @@ print_die (dw_die_ref die, FILE *outfile)
                   a->dw_attr_val.v.val_long_long.hi,
                   a->dw_attr_val.v.val_long_long.low);
          break;
-       case dw_val_class_float:
-         fprintf (outfile, "floating-point constant");
+       case dw_val_class_vec:
+         fprintf (outfile, "floating-point or vector constant");
          break;
        case dw_val_class_flag:
          fprintf (outfile, "%u", AT_flag (a));
@@ -5465,8 +5756,8 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
     case dw_val_class_long_long:
       CHECKSUM (at->dw_attr_val.v.val_long_long);
       break;
-    case dw_val_class_float:
-      CHECKSUM (at->dw_attr_val.v.val_float);
+    case dw_val_class_vec:
+      CHECKSUM (at->dw_attr_val.v.val_vec);
       break;
     case dw_val_class_flag:
       CHECKSUM (at->dw_attr_val.v.val_flag);
@@ -5477,15 +5768,8 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
 
     case dw_val_class_addr:
       r = AT_addr (at);
-      switch (GET_CODE (r))
-       {
-       case SYMBOL_REF:
-         CHECKSUM_STRING (XSTR (r, 0));
-         break;
-
-       default:
-         abort ();
-       }
+      gcc_assert (GET_CODE (r) == SYMBOL_REF);
+      CHECKSUM_STRING (XSTR (r, 0));
       break;
 
     case dw_val_class_offset:
@@ -5554,7 +5838,6 @@ same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark)
 {
   dw_loc_descr_ref loc1, loc2;
   rtx r1, r2;
-  unsigned i;
 
   if (v1->val_class != v2->val_class)
     return 0;
@@ -5568,12 +5851,13 @@ same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark)
     case dw_val_class_long_long:
       return v1->v.val_long_long.hi == v2->v.val_long_long.hi
             && v1->v.val_long_long.low == v2->v.val_long_long.low;
-    case dw_val_class_float:
-      if (v1->v.val_float.length != v2->v.val_float.length)
+    case dw_val_class_vec:
+      if (v1->v.val_vec.length != v2->v.val_vec.length
+         || v1->v.val_vec.elt_size != v2->v.val_vec.elt_size)
+       return 0;
+      if (memcmp (v1->v.val_vec.array, v2->v.val_vec.array,
+                 v1->v.val_vec.length * v1->v.val_vec.elt_size))
        return 0;
-      for (i = 0; i < v1->v.val_float.length; i++)
-       if (v1->v.val_float.array[i] != v2->v.val_float.array[i])
-         return 0;
       return 1;
     case dw_val_class_flag:
       return v1->v.val_flag == v2->v.val_flag;
@@ -5585,14 +5869,8 @@ same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark)
       r2 = v2->v.val_addr;
       if (GET_CODE (r1) != GET_CODE (r2))
        return 0;
-      switch (GET_CODE (r1))
-       {
-       case SYMBOL_REF:
-         return !strcmp (XSTR (r1, 0), XSTR (r2, 0));
-
-       default:
-         abort ();
-       }
+      gcc_assert (GET_CODE (r1) == SYMBOL_REF);
+      return !strcmp (XSTR (r1, 0), XSTR (r2, 0));
 
     case dw_val_class_offset:
       return v1->v.val_offset == v2->v.val_offset;
@@ -5968,8 +6246,7 @@ break_out_includes (dw_die_ref die)
 #if 0
   /* We can only use this in debugging, since the frontend doesn't check
      to make sure that we leave every include file we enter.  */
-  if (unit != NULL)
-    abort ();
+  gcc_assert (!unit);
 #endif
 
   assign_symbol_names (die);
@@ -6050,8 +6327,7 @@ build_abbrev_table (dw_die_ref die)
     if (AT_class (d_attr) == dw_val_class_die_ref
        && AT_ref (d_attr)->die_mark == 0)
       {
-       if (AT_ref (d_attr)->die_symbol == 0)
-         abort ();
+       gcc_assert (AT_ref (d_attr)->die_symbol);
 
        set_AT_ref_external (d_attr, 1);
       }
@@ -6167,8 +6443,9 @@ size_of_die (dw_die_ref die)
        case dw_val_class_long_long:
          size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */
          break;
-       case dw_val_class_float:
-         size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */
+       case dw_val_class_vec:
+         size += 1 + (a->dw_attr_val.v.val_vec.length
+                      * a->dw_attr_val.v.val_vec.elt_size); /* block */
          break;
        case dw_val_class_flag:
          size += 1;
@@ -6195,7 +6472,7 @@ size_of_die (dw_die_ref die)
            size += strlen (a->dw_attr_val.v.val_str->str) + 1;
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -6233,8 +6510,7 @@ mark_dies (dw_die_ref die)
 {
   dw_die_ref c;
 
-  if (die->die_mark)
-    abort ();
+  gcc_assert (!die->die_mark);
 
   die->die_mark = 1;
   for (c = die->die_child; c; c = c->die_sib)
@@ -6248,8 +6524,7 @@ unmark_dies (dw_die_ref die)
 {
   dw_die_ref c;
 
-  if (!die->die_mark)
-    abort ();
+  gcc_assert (die->die_mark);
 
   die->die_mark = 0;
   for (c = die->die_child; c; c = c->die_sib)
@@ -6325,11 +6600,15 @@ value_format (dw_attr_ref a)
       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 ();
+      switch (DWARF_OFFSET_SIZE)
+       {
+       case 4:
+         return DW_FORM_data4;
+       case 8:
+         return DW_FORM_data8;
+       default:
+         gcc_unreachable ();
+       }
     case dw_val_class_loc_list:
       /* FIXME: Could be DW_FORM_data8, with a > 32 bit size
         .debug_loc section */
@@ -6342,7 +6621,7 @@ value_format (dw_attr_ref a)
        case 2:
          return DW_FORM_block2;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     case dw_val_class_const:
       return DW_FORM_sdata;
@@ -6358,11 +6637,11 @@ value_format (dw_attr_ref a)
        case 8:
          return DW_FORM_data8;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     case dw_val_class_long_long:
       return DW_FORM_block1;
-    case dw_val_class_float:
+    case dw_val_class_vec:
       return DW_FORM_block1;
     case dw_val_class_flag:
       return DW_FORM_flag;
@@ -6381,7 +6660,7 @@ value_format (dw_attr_ref a)
       return AT_string_form (a);
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -6448,7 +6727,7 @@ output_die_symbol (dw_die_ref die)
     /* We make these global, not weak; if the target doesn't support
        .linkonce, it doesn't support combining the sections, so debugging
        will break.  */
-    (*targetm.asm_out.globalize_label) (asm_out_file, sym);
+    targetm.asm_out.globalize_label (asm_out_file, sym);
 
   ASM_OUTPUT_LABEL (asm_out_file, sym);
 }
@@ -6499,42 +6778,41 @@ output_loc_list (dw_loc_list_ref 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");
-    }
-
+  /* Walk the location list, and output each range + expression.  */
   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);
+      if (separate_line_info_table_in_use == 0)
+       {
+         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);
+       }
+      else
+       {
+         dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin,
+                              "Location list begin address (%s)",
+                              list_head->ll_symbol);
+         dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->end,
+                              "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 ();
+      gcc_assert (size <= 0xffff);
       dw2_asm_output_data (2, size, "%s", "Location expression size");
 
       output_loc_sequence (curr->expr);
     }
 
-  dw2_asm_output_data (DWARF_OFFSET_SIZE, 0,
+  dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
                       "Location list terminator begin (%s)",
                       list_head->ll_symbol);
-  dw2_asm_output_data (DWARF_OFFSET_SIZE, 0,
+  dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
                       "Location list terminator end (%s)",
                       list_head->ll_symbol);
 }
@@ -6631,16 +6909,24 @@ output_die (dw_die_ref die)
          }
          break;
 
-       case dw_val_class_float:
+       case dw_val_class_vec:
          {
+           unsigned int elt_size = a->dw_attr_val.v.val_vec.elt_size;
+           unsigned int len = a->dw_attr_val.v.val_vec.length;
            unsigned int i;
+           unsigned char *p;
 
-           dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4,
-                                "%s", name);
-
-           for (i = 0; i < a->dw_attr_val.v.val_float.length; i++)
-             dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i],
-                                  "fp constant word %u", i);
+           dw2_asm_output_data (1, len * elt_size, "%s", name);
+           if (elt_size > sizeof (HOST_WIDE_INT))
+             {
+               elt_size /= 2;
+               len *= 2;
+             }
+           for (i = 0, p = a->dw_attr_val.v.val_vec.array;
+                i < len;
+                i++, p += elt_size)
+             dw2_asm_output_data (elt_size, extract_int (p, elt_size),
+                                  "fp or vector constant word %u", i);
            break;
          }
 
@@ -6652,10 +6938,8 @@ output_die (dw_die_ref die)
          {
            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);
+           gcc_assert (sym);
+           dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, "%s", name);
          }
          break;
 
@@ -6664,15 +6948,15 @@ output_die (dw_die_ref die)
            {
              char *sym = AT_ref (a)->die_symbol;
 
-             if (sym == 0)
-               abort ();
+             gcc_assert (sym);
              dw2_asm_output_offset (DWARF2_ADDR_SIZE, sym, "%s", name);
            }
-         else if (AT_ref (a)->die_offset == 0)
-           abort ();
          else
-           dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset,
-                                "%s", name);
+           {
+             gcc_assert (AT_ref (a)->die_offset);
+             dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset,
+                                  "%s", name);
+           }
          break;
 
        case dw_val_class_fde_ref:
@@ -6703,7 +6987,7 @@ output_die (dw_die_ref die)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -6792,7 +7076,7 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
 static const char *
 dwarf2_name (tree decl, int scope)
 {
-  return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
+  return lang_hooks.decl_printable_name (decl, scope ? 1 : 0);
 }
 
 /* Add a new entry to .debug_pubnames if appropriate.  */
@@ -6846,8 +7130,7 @@ output_pubnames (void)
       pubname_ref pub = &pubname_table[i];
 
       /* We shouldn't see pubnames for DIEs outside of the main CU.  */
-      if (pub->die->die_mark == 0)
-       abort ();
+      gcc_assert (pub->die->die_mark);
 
       dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
                           "DIE offset");
@@ -6920,8 +7203,7 @@ output_aranges (void)
       dw_die_ref die = arange_table[i];
 
       /* We shouldn't see aranges for DIEs outside of the main CU.  */
-      if (die->die_mark == 0)
-       abort ();
+      gcc_assert (die->die_mark);
 
       if (die->die_tag == DW_TAG_subprogram)
        {
@@ -6938,12 +7220,10 @@ output_aranges (void)
          dw_attr_ref a = get_AT (die, DW_AT_location);
          dw_loc_descr_ref loc;
 
-         if (! a || AT_class (a) != dw_val_class_loc)
-           abort ();
+         gcc_assert (a && AT_class (a) == dw_val_class_loc);
 
          loc = AT_loc (a);
-         if (loc->dw_loc_opc != DW_OP_addr)
-           abort ();
+         gcc_assert (loc->dw_loc_opc == DW_OP_addr);
 
          dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE,
                                   loc->dw_loc_oprnd1.v.val_addr, "Address");
@@ -7662,7 +7942,7 @@ base_type_die (tree type)
                 || ! strcmp (type_name, "signed char")
                 || ! strcmp (type_name, "unsigned char"))))
        {
-         if (TREE_UNSIGNED (type))
+         if (TYPE_UNSIGNED (type))
            encoding = DW_ATE_unsigned;
          else
            encoding = DW_ATE_signed;
@@ -7672,7 +7952,7 @@ base_type_die (tree type)
 
     case CHAR_TYPE:
       /* GNU Pascal/Ada CHAR type.  Not used in C.  */
-      if (TREE_UNSIGNED (type))
+      if (TYPE_UNSIGNED (type))
        encoding = DW_ATE_unsigned_char;
       else
        encoding = DW_ATE_signed_char;
@@ -7698,7 +7978,7 @@ base_type_die (tree type)
 
     default:
       /* No other TREE_CODEs are Dwarf fundamental types.  */
-      abort ();
+      gcc_unreachable ();
     }
 
   base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type);
@@ -7759,7 +8039,6 @@ is_base_type (tree type)
     case CHAR_TYPE:
       return 1;
 
-    case SET_TYPE:
     case ARRAY_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -7776,7 +8055,7 @@ is_base_type (tree type)
       return 0;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return 0;
@@ -7805,29 +8084,55 @@ simple_type_size_in_bits (tree type)
    emitted as a subrange type.  */
 
 static inline bool
-is_ada_subrange_type (tree type)
-{
-  /* We should use a subrange type in the following situations:
-     - For Ada modular types: These types are stored as integer subtypes
-       of an unsigned integer type;
-     - For subtypes of an Ada enumeration type: These types are stored
-       as integer subtypes of enumeral types.
-     
-     This subrange type is mostly for the benefit of debugger users.
-     A nameless type would therefore not be very useful, so no need
-     to generate a subrange type in these cases.  */
+is_subrange_type (tree type)
+{
   tree subtype = TREE_TYPE (type);
 
-  if (is_ada ()
-      && TREE_CODE (type) == INTEGER_TYPE
-      && subtype != NULL_TREE)
+  /* Subrange types are identified by the fact that they are integer
+     types, and that they have a subtype which is either an integer type
+     or an enumeral type.  */
+
+  if (TREE_CODE (type) != INTEGER_TYPE
+      || subtype == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (subtype) != INTEGER_TYPE
+      && TREE_CODE (subtype) != ENUMERAL_TYPE)
+    return false;
+
+  if (TREE_CODE (type) == TREE_CODE (subtype)
+      && int_size_in_bytes (type) == int_size_in_bytes (subtype)
+      && TYPE_MIN_VALUE (type) != NULL
+      && TYPE_MIN_VALUE (subtype) != NULL
+      && tree_int_cst_equal (TYPE_MIN_VALUE (type), TYPE_MIN_VALUE (subtype))
+      && TYPE_MAX_VALUE (type) != NULL
+      && TYPE_MAX_VALUE (subtype) != NULL
+      && tree_int_cst_equal (TYPE_MAX_VALUE (type), TYPE_MAX_VALUE (subtype)))
     {
-      if (TREE_CODE (subtype) == INTEGER_TYPE && TREE_UNSIGNED (subtype))
-        return true;
-      if (TREE_CODE (subtype) == ENUMERAL_TYPE)
-        return true;
+      /* The type and its subtype have the same representation.  If in
+         addition the two types also have the same name, then the given
+         type is not a subrange type, but rather a plain base type.  */
+      /* FIXME: brobecker/2004-03-22:
+         Sizetype INTEGER_CSTs nodes are canonicalized.  It should
+         therefore be sufficient to check the TYPE_SIZE node pointers
+         rather than checking the actual size.  Unfortunately, we have
+         found some cases, such as in the Ada "integer" type, where
+         this is not the case.  Until this problem is solved, we need to
+         keep checking the actual size.  */
+      tree type_name = TYPE_NAME (type);
+      tree subtype_name = TYPE_NAME (subtype);
+
+      if (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
+        type_name = DECL_NAME (type_name);
+
+      if (subtype_name != NULL && TREE_CODE (subtype_name) == TYPE_DECL)
+        subtype_name = DECL_NAME (subtype_name);
+
+      if (type_name == subtype_name)
+        return false;
     }
-  return false;
+
+  return true;
 }
 
 /*  Given a pointer to a tree node for a subrange type, return a pointer
@@ -7839,14 +8144,16 @@ subrange_type_die (tree type, dw_die_ref context_die)
   dw_die_ref subtype_die;
   dw_die_ref subrange_die;
   tree name = TYPE_NAME (type);
+  const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
+  tree subtype = TREE_TYPE (type);
 
   if (context_die == NULL)
     context_die = comp_unit_die;
 
-  if (TREE_CODE (TREE_TYPE (type)) == ENUMERAL_TYPE)
-    subtype_die = gen_enumeration_type_die (TREE_TYPE (type), context_die);
+  if (TREE_CODE (subtype) == ENUMERAL_TYPE)
+    subtype_die = gen_enumeration_type_die (subtype, context_die);
   else
-    subtype_die = base_type_die (TREE_TYPE (type));
+    subtype_die = base_type_die (subtype);
 
   subrange_die = new_die (DW_TAG_subrange_type, context_die, type);
 
@@ -7857,6 +8164,13 @@ subrange_type_die (tree type, dw_die_ref context_die)
       add_name_attribute (subrange_die, IDENTIFIER_POINTER (name));
     }
 
+  if (int_size_in_bytes (subtype) != size_in_bytes)
+    {
+      /* The size of the subrange type and its base type do not match,
+         so we need to generate a size attribute for the subrange type.  */
+      add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes);
+    }
+
   if (TYPE_MIN_VALUE (type) != NULL)
     add_bound_info (subrange_die, DW_AT_lower_bound,
                     TYPE_MIN_VALUE (type));
@@ -7959,7 +8273,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
 #endif
          item_type = TREE_TYPE (type);
        }
-      else if (is_ada_subrange_type (type))
+      else if (is_subrange_type (type))
         mod_type_die = subrange_type_die (type, context_die);
       else if (is_base_type (type))
        mod_type_die = base_type_die (type);
@@ -7979,8 +8293,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
            /* Vectors have the debugging information in the type,
               not the main variant.  */
            mod_type_die = lookup_type_die (type);
-         if (mod_type_die == NULL)
-           abort ();
+         gcc_assert (mod_type_die);
        }
 
       /* We want to equate the qualified type to the die below.  */
@@ -8014,15 +8327,14 @@ type_is_enum (tree type)
   return TREE_CODE (type) == ENUMERAL_TYPE;
 }
 
-/* Return the register number described by a given RTL node.  */
+/* Return the DBX register number described by a given RTL node.  */
 
 static unsigned int
-reg_number (rtx rtl)
+dbx_reg_number (rtx rtl)
 {
   unsigned regno = REGNO (rtl);
 
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    abort ();
+  gcc_assert (regno < FIRST_PSEUDO_REGISTER);
 
   return DBX_REGISTER_NUMBER (regno);
 }
@@ -8039,10 +8351,10 @@ reg_loc_descriptor (rtx rtl)
   if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
     return 0;
 
-  reg = reg_number (rtl);
-  regs = (*targetm.dwarf_register_span) (rtl);
+  reg = dbx_reg_number (rtl);
+  regs = targetm.dwarf_register_span (rtl);
 
-  if (HARD_REGNO_NREGS (reg, GET_MODE (rtl)) > 1
+  if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1
       || regs)
     return multiple_reg_loc_descriptor (rtl, regs);
   else
@@ -8071,8 +8383,8 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
   unsigned reg;
   dw_loc_descr_ref loc_result = NULL;
 
-  reg = reg_number (rtl);
-  nregs = HARD_REGNO_NREGS (reg, GET_MODE (rtl));
+  reg = dbx_reg_number (rtl);
+  nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
 
   /* Simple, contiguous registers.  */
   if (regs == NULL_RTX)
@@ -8094,8 +8406,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
 
   /* Now onto stupid register sets in non contiguous locations.  */
 
-  if (GET_CODE (regs) != PARALLEL)
-    abort ();
+  gcc_assert (GET_CODE (regs) == PARALLEL);
 
   size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
   loc_result = NULL;
@@ -8154,7 +8465,7 @@ int_loc_descriptor (HOST_WIDE_INT i)
 /* Return a location descriptor that designates a base+offset location.  */
 
 static dw_loc_descr_ref
-based_loc_descr (unsigned int reg, HOST_WIDE_INT offset)
+based_loc_descr (unsigned int reg, HOST_WIDE_INT offset, bool can_use_fbreg)
 {
   dw_loc_descr_ref loc_result;
   /* For the "frame base", we use the frame pointer or stack pointer
@@ -8164,7 +8475,7 @@ based_loc_descr (unsigned int reg, HOST_WIDE_INT offset)
                                         ? HARD_FRAME_POINTER_REGNUM
                                         : STACK_POINTER_REGNUM);
 
-  if (reg == fp_reg)
+  if (reg == fp_reg && can_use_fbreg)
     loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
   else if (reg <= 31)
     loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0);
@@ -8180,7 +8491,7 @@ static inline int
 is_based_loc (rtx rtl)
 {
   return (GET_CODE (rtl) == PLUS
-         && ((GET_CODE (XEXP (rtl, 0)) == REG
+         && ((REG_P (XEXP (rtl, 0))
               && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
               && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
 }
@@ -8198,19 +8509,25 @@ is_based_loc (rtx rtl)
    MODE is the mode of the memory reference, needed to handle some
    autoincrement addressing modes.
 
+   CAN_USE_FBREG is a flag whether we can use DW_AT_frame_base in the location
+   list for RTL. We can't use it when we are emitting location list for
+   virtual variable frame_base_decl (i.e. a location list for DW_AT_frame_base)
+   which describes how frame base changes when !frame_pointer_needed.
+
    Return 0 if we can't represent the location.  */
 
 static dw_loc_descr_ref
-mem_loc_descriptor (rtx rtl, enum machine_mode mode)
+mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
 {
   dw_loc_descr_ref mem_loc_result = NULL;
+  enum dwarf_location_atom op;
 
   /* 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
      zeroth element of the array.  */
 
-  rtl = (*targetm.delegitimize_address) (rtl);
+  rtl = targetm.delegitimize_address (rtl);
 
   switch (GET_CODE (rtl))
     {
@@ -8247,11 +8564,13 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
         memory) so DWARF consumers need to be aware of the subtle
         distinction between OP_REG and OP_BASEREG.  */
       if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
-       mem_loc_result = based_loc_descr (reg_number (rtl), 0);
+       mem_loc_result = based_loc_descr (dbx_reg_number (rtl), 0,
+                                         can_use_fbreg);
       break;
 
     case MEM:
-      mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
+      mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
+                                          can_use_fbreg);
       if (mem_loc_result != 0)
        add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
       break;
@@ -8317,11 +8636,13 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
     case PLUS:
     plus:
       if (is_based_loc (rtl))
-       mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
-                                         INTVAL (XEXP (rtl, 1)));
+       mem_loc_result = based_loc_descr (dbx_reg_number (XEXP (rtl, 0)),
+                                         INTVAL (XEXP (rtl, 1)),
+                                         can_use_fbreg);
       else
        {
-         mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
+         mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode,
+                                              can_use_fbreg);
          if (mem_loc_result == 0)
            break;
 
@@ -8333,26 +8654,45 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
          else
            {
              add_loc_descr (&mem_loc_result,
-                            mem_loc_descriptor (XEXP (rtl, 1), mode));
+                            mem_loc_descriptor (XEXP (rtl, 1), mode,
+                                                can_use_fbreg));
              add_loc_descr (&mem_loc_result,
                             new_loc_descr (DW_OP_plus, 0, 0));
            }
        }
       break;
 
+    /* If a pseudo-reg is optimized away, it is possible for it to
+       be replaced with a MEM containing a multiply or shift.  */
     case MULT:
-      {
-       /* 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);
+      op = DW_OP_mul;
+      goto do_binop;
+
+    case ASHIFT:
+      op = DW_OP_shl;
+      goto do_binop;
+
+    case ASHIFTRT:
+      op = DW_OP_shra;
+      goto do_binop;
+
+    case LSHIFTRT:
+      op = DW_OP_shr;
+      goto do_binop;
+
+    do_binop:
+      {
+       dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
+                                                  can_use_fbreg);
+       dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
+                                                  can_use_fbreg);
 
        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));
+       add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
        break;
       }
 
@@ -8360,16 +8700,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
       mem_loc_result = int_loc_descriptor (INTVAL (rtl));
       break;
 
-    case ADDRESSOF:
-      /* If this is a MEM, return its address.  Otherwise, we can't
-        represent this.  */
-      if (GET_CODE (XEXP (rtl, 0)) == MEM)
-       return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode);
-      else
-       return 0;
-
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return mem_loc_result;
@@ -8382,8 +8714,8 @@ static dw_loc_descr_ref
 concat_loc_descriptor (rtx x0, rtx 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);
+  dw_loc_descr_ref x0_ref = loc_descriptor (x0, false);
+  dw_loc_descr_ref x1_ref = loc_descriptor (x1, false);
 
   if (x0_ref == 0 || x1_ref == 0)
     return 0;
@@ -8410,7 +8742,7 @@ concat_loc_descriptor (rtx x0, rtx x1)
    If we don't know how to describe it, return 0.  */
 
 static dw_loc_descr_ref
-loc_descriptor (rtx rtl)
+loc_descriptor (rtx rtl, bool can_use_fbreg)
 {
   dw_loc_descr_ref loc_result = NULL;
 
@@ -8431,31 +8763,72 @@ loc_descriptor (rtx rtl)
       break;
 
     case MEM:
-      loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
+      loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
+                                      can_use_fbreg);
       break;
 
     case CONCAT:
       loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
       break;
 
+    case VAR_LOCATION:
+      /* Single part.  */
+      if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
+       {
+         loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg);
+         break;
+       }
+
+      rtl = XEXP (rtl, 1);
+      /* FALLTHRU */
+
+    case PARALLEL:
+      {
+       rtvec par_elems = XVEC (rtl, 0);
+       int num_elem = GET_NUM_ELEM (par_elems);
+       enum machine_mode mode;
+       int i;
+
+       /* Create the first one, so we have something to add to.  */
+       loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
+                                    can_use_fbreg);
+       mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
+       add_loc_descr (&loc_result,
+                      new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
+       for (i = 1; i < num_elem; i++)
+         {
+           dw_loc_descr_ref temp;
+
+           temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
+                                  can_use_fbreg);
+           add_loc_descr (&loc_result, temp);
+           mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
+           add_loc_descr (&loc_result,
+                          new_loc_descr (DW_OP_piece,
+                                         GET_MODE_SIZE (mode), 0));
+         }
+      }
+      break;
+
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return loc_result;
 }
 
 /* Similar, but generate the descriptor from trees instead of rtl.  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 make a
-   descriptor, return 0.  */
+   up particularly with variable length arrays.  WANT_ADDRESS is 2 if this is
+   a top-level invocation of loc_descriptor_from_tree; is 1 if this is not a
+   top-level invocation, and we require the address of LOC; is 0 if we require
+   the value of LOC.  */
 
 static dw_loc_descr_ref
-loc_descriptor_from_tree (tree loc, int addressp)
+loc_descriptor_from_tree_1 (tree loc, int want_address)
 {
   dw_loc_descr_ref ret, ret1;
-  int indirect_p = 0;
-  int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
+  int have_address = 0;
+  int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
   enum dwarf_location_atom op;
 
   /* ??? Most of the time we do not take proper care for sign/zero
@@ -8467,7 +8840,6 @@ loc_descriptor_from_tree (tree loc, int addressp)
     case ERROR_MARK:
       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
@@ -8478,20 +8850,20 @@ loc_descriptor_from_tree (tree loc, int addressp)
     case CALL_EXPR:
       return 0;
 
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+      /* There are no opcodes for these operations.  */
+      return 0;
+
     case ADDR_EXPR:
-      /* We can support this only if we can look through conversions and
-        find an INDIRECT_EXPR.  */
-      for (loc = TREE_OPERAND (loc, 0);
-          TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR
-          || TREE_CODE (loc) == NON_LVALUE_EXPR
-          || TREE_CODE (loc) == VIEW_CONVERT_EXPR
-          || TREE_CODE (loc) == SAVE_EXPR;
-          loc = TREE_OPERAND (loc, 0))
-       ;
+      /* If we already want an address, there's nothing we can do.  */
+      if (want_address)
+       return 0;
 
-       return (TREE_CODE (loc) == INDIRECT_REF
-              ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp)
-              : 0);
+      /* Otherwise, process the argument and look for the address.  */
+      return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1);
 
     case VAR_DECL:
       if (DECL_THREAD_LOCAL (loc))
@@ -8512,7 +8884,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
          if (rtl == NULL_RTX)
            return 0;
 
-         if (GET_CODE (rtl) != MEM)
+         if (!MEM_P (rtl))
            return 0;
          rtl = XEXP (rtl, 0);
          if (! CONSTANT_P (rtl))
@@ -8525,46 +8897,63 @@ loc_descriptor_from_tree (tree loc, int addressp)
          ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
          add_loc_descr (&ret, ret1);
 
-         indirect_p = 1;
+         have_address = 1;
          break;
        }
-      /* Fall through.  */
+      /* FALLTHRU */
 
     case PARM_DECL:
+      if (DECL_VALUE_EXPR (loc))
+       return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc), want_address);
+      /* FALLTHRU */
+
+    case RESULT_DECL:
       {
        rtx rtl = rtl_for_decl_location (loc);
 
        if (rtl == NULL_RTX)
          return 0;
+        else if (GET_CODE (rtl) == CONST_INT)
+         {
+           HOST_WIDE_INT val = INTVAL (rtl);
+           if (TYPE_UNSIGNED (TREE_TYPE (loc)))
+             val &= GET_MODE_MASK (DECL_MODE (loc));
+           ret = int_loc_descriptor (val);
+         }
+       else if (GET_CODE (rtl) == CONST_STRING)
+         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_p = 1;
          }
        else
          {
-           enum machine_mode mode = GET_MODE (rtl);
+           enum machine_mode mode;
+
+           /* Certain constructs can only be represented at top-level.  */
+           if (want_address == 2)
+             return loc_descriptor (rtl, false);
 
-           if (GET_CODE (rtl) == MEM)
+           mode = GET_MODE (rtl);
+           if (MEM_P (rtl))
              {
-               indirect_p = 1;
                rtl = XEXP (rtl, 0);
+               have_address = 1;
              }
-
-           ret = mem_loc_descriptor (rtl, mode);
+           ret = mem_loc_descriptor (rtl, mode, false);
          }
       }
       break;
 
     case INDIRECT_REF:
-      ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
-      indirect_p = 1;
+      ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
+      have_address = 1;
       break;
 
     case COMPOUND_EXPR:
-      return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp);
+      return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), want_address);
 
     case NOP_EXPR:
     case CONVERT_EXPR:
@@ -8572,7 +8961,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
     case MODIFY_EXPR:
-      return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp);
+      return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -8585,12 +8974,12 @@ loc_descriptor_from_tree (tree loc, int addressp)
        int volatilep;
 
        obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
-                                  &unsignedp, &volatilep);
+                                  &unsignedp, &volatilep, false);
 
        if (obj == loc)
          return 0;
 
-       ret = loc_descriptor_from_tree (obj, 1);
+       ret = loc_descriptor_from_tree_1 (obj, 1);
        if (ret == 0
            || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
          return 0;
@@ -8598,13 +8987,10 @@ loc_descriptor_from_tree (tree loc, int addressp)
        if (offset != NULL_TREE)
          {
            /* Variable offset.  */
-           add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0));
+           add_loc_descr (&ret, loc_descriptor_from_tree_1 (offset, 0));
            add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
          }
 
-       if (!addressp)
-         indirect_p = 1;
-
        bytepos = bitpos / BITS_PER_UNIT;
        if (bytepos > 0)
          add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
@@ -8613,6 +8999,8 @@ loc_descriptor_from_tree (tree loc, int addressp)
            add_loc_descr (&ret, int_loc_descriptor (bytepos));
            add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
          }
+
+       have_address = 1;
        break;
       }
 
@@ -8629,15 +9017,12 @@ loc_descriptor_from_tree (tree loc, int addressp)
        rtx rtl = lookup_constant_def (loc);
        enum machine_mode mode;
 
-       if (GET_CODE (rtl) != MEM)
+       if (!rtl || !MEM_P (rtl))
          return 0;
        mode = GET_MODE (rtl);
        rtl = XEXP (rtl, 0);
-
-       rtl = (*targetm.delegitimize_address) (rtl);
-
-       indirect_p = 1;
-       ret = mem_loc_descriptor (rtl, mode);
+       ret = mem_loc_descriptor (rtl, mode, false);
+       have_address = 1;
        break;
       }
 
@@ -8692,7 +9077,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
       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);
+         ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
          if (ret == 0)
            return 0;
 
@@ -8708,28 +9093,28 @@ loc_descriptor_from_tree (tree loc, int addressp)
       goto do_binop;
 
     case LE_EXPR:
-      if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
        return 0;
 
       op = DW_OP_le;
       goto do_binop;
 
     case GE_EXPR:
-      if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
        return 0;
 
       op = DW_OP_ge;
       goto do_binop;
 
     case LT_EXPR:
-      if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
        return 0;
 
       op = DW_OP_lt;
       goto do_binop;
 
     case GT_EXPR:
-      if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
        return 0;
 
       op = DW_OP_gt;
@@ -8744,8 +9129,8 @@ loc_descriptor_from_tree (tree loc, int addressp)
       goto do_binop;
 
     do_binop:
-      ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
-      ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+      ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
+      ret1 = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
       if (ret == 0 || ret1 == 0)
        return 0;
 
@@ -8767,30 +9152,36 @@ loc_descriptor_from_tree (tree loc, int addressp)
       goto do_unop;
 
     do_unop:
-      ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+      ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
       if (ret == 0)
        return 0;
 
       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
       break;
 
+    case MIN_EXPR:
     case MAX_EXPR:
-      loc = build (COND_EXPR, TREE_TYPE (loc),
-                  build (LT_EXPR, integer_type_node,
-                         TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
-                  TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+      {
+        const enum tree_code code =
+          TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
+
+        loc = build3 (COND_EXPR, TREE_TYPE (loc),
+                     build2 (code, integer_type_node,
+                             TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
+                      TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+      }
 
       /* ... fall through ...  */
 
     case COND_EXPR:
       {
        dw_loc_descr_ref lhs
-         = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+         = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
        dw_loc_descr_ref rhs
-         = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
+         = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 2), 0);
        dw_loc_descr_ref bra_node, jump_node, tmp;
 
-       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
        if (ret == 0 || lhs == 0 || rhs == 0)
          return 0;
 
@@ -8813,6 +9204,12 @@ loc_descriptor_from_tree (tree loc, int addressp)
       }
       break;
 
+    case FIX_TRUNC_EXPR:
+    case FIX_CEIL_EXPR:
+    case FIX_FLOOR_EXPR:
+    case FIX_ROUND_EXPR:
+      return 0;
+
     default:
       /* Leave front-end specific codes as simply unknown.  This comes
         up, for instance, with the C STMT_EXPR.  */
@@ -8820,17 +9217,23 @@ loc_descriptor_from_tree (tree loc, int addressp)
           >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
        return 0;
 
+#ifdef ENABLE_CHECKING
       /* Otherwise this is a generic code; we should just lists all of
         these explicitly.  Aborting means we forgot one.  */
-      abort ();
+      gcc_unreachable ();
+#else
+      /* In a release build, we want to degrade gracefully: better to
+        generate incomplete debugging information than to crash.  */
+      return NULL;
+#endif
     }
 
   /* Show if we can't fill the request for an address.  */
-  if (addressp && indirect_p == 0)
+  if (want_address && !have_address)
     return 0;
 
   /* If we've got an address and don't want one, dereference.  */
-  if (!addressp && indirect_p > 0)
+  if (!want_address && have_address)
     {
       HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
 
@@ -8847,6 +9250,12 @@ loc_descriptor_from_tree (tree loc, int addressp)
   return ret;
 }
 
+static inline dw_loc_descr_ref
+loc_descriptor_from_tree (tree loc)
+{
+  return loc_descriptor_from_tree_1 (loc, 2);
+}
+
 /* Given a value, round it up to the lowest multiple of `boundary'
    which is not less than the value itself.  */
 
@@ -8914,8 +9323,8 @@ field_byte_offset (tree decl)
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return 0;
-  else if (TREE_CODE (decl) != FIELD_DECL)
-    abort ();
+
+  gcc_assert (TREE_CODE (decl) == FIELD_DECL);
 
   type = field_type (decl);
   field_size_tree = DECL_SIZE (decl);
@@ -9051,10 +9460,10 @@ add_data_member_location_attribute (dw_die_ref die, tree decl)
   HOST_WIDE_INT offset;
   dw_loc_descr_ref loc_descr = 0;
 
-  if (TREE_CODE (decl) == TREE_VEC)
+  if (TREE_CODE (decl) == TREE_BINFO)
     {
       /* We're working on the TAG_inheritance for a base class.  */
-      if (TREE_VIA_VIRTUAL (decl) && is_cxx ())
+      if (BINFO_VIRTUAL_P (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
@@ -9077,8 +9486,7 @@ add_data_member_location_attribute (dw_die_ref die, tree decl)
 
          /* Calculate the address of the offset.  */
          offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0);
-         if (offset >= 0)
-           abort ();
+         gcc_assert (offset < 0);
 
          tmp = int_loc_descriptor (-offset);
          add_loc_descr (&loc_descr, tmp);
@@ -9122,6 +9530,56 @@ add_data_member_location_attribute (dw_die_ref die, tree decl)
   add_AT_loc (die, DW_AT_data_member_location, loc_descr);
 }
 
+/* Writes integer values to dw_vec_const array.  */
+
+static void
+insert_int (HOST_WIDE_INT val, unsigned int size, unsigned char *dest)
+{
+  while (size != 0)
+    {
+      *dest++ = val & 0xff;
+      val >>= 8;
+      --size;
+    }
+}
+
+/* Reads integers from dw_vec_const array.  Inverse of insert_int.  */
+
+static HOST_WIDE_INT
+extract_int (const unsigned char *src, unsigned int size)
+{
+  HOST_WIDE_INT val = 0;
+
+  src += size;
+  while (size != 0)
+    {
+      val <<= 8;
+      val |= *--src & 0xff;
+      --size;
+    }
+  return val;
+}
+
+/* Writes floating point values to dw_vec_const array.  */
+
+static void
+insert_float (rtx rtl, unsigned char *array)
+{
+  REAL_VALUE_TYPE rv;
+  long val[4];
+  int i;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
+  real_to_target (val, &rv, GET_MODE (rtl));
+
+  /* real_to_target puts 32-bit pieces in each long.  Pack them.  */
+  for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
+    {
+      insert_int (val[i], 4, array);
+      array += 4;
+    }
+}
+
 /* Attach a DW_AT_const_value attribute for a variable or a parameter which
    does not have a "location" either in memory or in a register.  These
    things can arise in GNU C when a constant is passed as an actual parameter
@@ -9139,7 +9597,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
 
        if (val < 0)
          add_AT_int (die, DW_AT_const_value, val);
-       else 
+       else
          add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
       }
       break;
@@ -9154,20 +9612,16 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
 
        if (GET_MODE_CLASS (mode) == MODE_FLOAT)
          {
-           unsigned length = GET_MODE_SIZE (mode) / 4;
-           long *array = ggc_alloc (sizeof (long) * length);
-           REAL_VALUE_TYPE rv;
-
-           REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
-           real_to_target (array, &rv, mode);
+           unsigned int length = GET_MODE_SIZE (mode);
+           unsigned char *array = ggc_alloc (length);
 
-           add_AT_float (die, DW_AT_const_value, length, array);
+           insert_float (rtl, array);
+           add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
          }
        else
          {
            /* ??? We really should be using HOST_WIDE_INT throughout.  */
-           if (HOST_BITS_PER_LONG != HOST_BITS_PER_WIDE_INT)
-             abort ();
+           gcc_assert (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT);
 
            add_AT_long_long (die, DW_AT_const_value,
                              CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
@@ -9175,6 +9629,74 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
       }
       break;
 
+    case CONST_VECTOR:
+      {
+       enum machine_mode mode = GET_MODE (rtl);
+       unsigned int elt_size = GET_MODE_UNIT_SIZE (mode);
+       unsigned int length = CONST_VECTOR_NUNITS (rtl);
+       unsigned char *array = ggc_alloc (length * elt_size);
+       unsigned int i;
+       unsigned char *p;
+
+       switch (GET_MODE_CLASS (mode))
+         {
+         case MODE_VECTOR_INT:
+           for (i = 0, p = array; i < length; i++, p += elt_size)
+             {
+               rtx elt = CONST_VECTOR_ELT (rtl, i);
+               HOST_WIDE_INT lo, hi;
+
+               switch (GET_CODE (elt))
+                 {
+                 case CONST_INT:
+                   lo = INTVAL (elt);
+                   hi = -(lo < 0);
+                   break;
+
+                 case CONST_DOUBLE:
+                   lo = CONST_DOUBLE_LOW (elt);
+                   hi = CONST_DOUBLE_HIGH (elt);
+                   break;
+
+                 default:
+                   gcc_unreachable ();
+                 }
+
+               if (elt_size <= sizeof (HOST_WIDE_INT))
+                 insert_int (lo, elt_size, p);
+               else
+                 {
+                   unsigned char *p0 = p;
+                   unsigned char *p1 = p + sizeof (HOST_WIDE_INT);
+
+                   gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
+                   if (WORDS_BIG_ENDIAN)
+                     {
+                       p0 = p1;
+                       p1 = p;
+                     }
+                   insert_int (lo, sizeof (HOST_WIDE_INT), p0);
+                   insert_int (hi, sizeof (HOST_WIDE_INT), p1);
+                 }
+             }
+           break;
+
+         case MODE_VECTOR_FLOAT:
+           for (i = 0, p = array; i < length; i++, p += elt_size)
+             {
+               rtx elt = CONST_VECTOR_ELT (rtl, i);
+               insert_float (elt, p);
+             }
+           break;
+
+         default:
+           gcc_unreachable ();
+         }
+
+       add_AT_vec (die, DW_AT_const_value, length, elt_size, array);
+      }
+      break;
+
     case CONST_STRING:
       add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0));
       break;
@@ -9202,7 +9724,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
 
     default:
       /* No other kinds of rtx should be possible here.  */
-      abort ();
+      gcc_unreachable ();
     }
 
 }
@@ -9280,10 +9802,7 @@ rtl_for_decl_location (tree decl)
      This happens (for example) for inlined-instances of inline function formal
      parameters which are never referenced.  This really shouldn't be
      happening.  All PARM_DECL nodes should get valid non-NULL
-     DECL_INCOMING_RTL values, but integrate.c doesn't currently generate these
-     values for inlined instances of inline function parameters, so when we see
-     such cases, we are just out-of-luck for the time being (until integrate.c
-     gets fixed).  */
+     DECL_INCOMING_RTL values.  FIXME.  */
 
   /* Use DECL_RTL as the "location" unless we find something better.  */
   rtl = DECL_RTL_IF_SET (decl);
@@ -9295,13 +9814,13 @@ rtl_for_decl_location (tree decl)
     {
       if (rtl
          && (CONSTANT_P (rtl)
-             || (GET_CODE (rtl) == MEM
+             || (MEM_P (rtl)
                  && CONSTANT_P (XEXP (rtl, 0)))
-             || (GET_CODE (rtl) == REG
+             || (REG_P (rtl)
                  && TREE_CODE (decl) == VAR_DECL
                  && TREE_STATIC (decl))))
        {
-         rtl = (*targetm.delegitimize_address) (rtl);
+         rtl = targetm.delegitimize_address (rtl);
          return rtl;
        }
       rtl = NULL_RTX;
@@ -9310,19 +9829,33 @@ rtl_for_decl_location (tree decl)
     {
       if (rtl == NULL_RTX || is_pseudo_reg (rtl))
        {
-         tree declared_type = type_main_variant (TREE_TYPE (decl));
-         tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
+         tree declared_type = TREE_TYPE (decl);
+         tree passed_type = DECL_ARG_TYPE (decl);
+         enum machine_mode dmode = TYPE_MODE (declared_type);
+         enum machine_mode pmode = TYPE_MODE (passed_type);
 
          /* This decl represents a formal parameter which was optimized out.
             Note that DECL_INCOMING_RTL may be NULL in here, but we handle
             all cases where (rtl == NULL_RTX) just below.  */
-         if (declared_type == passed_type)
-           rtl = DECL_INCOMING_RTL (decl);
-         else if (! BYTES_BIG_ENDIAN
-                  && TREE_CODE (declared_type) == INTEGER_TYPE
-                  && (GET_MODE_SIZE (TYPE_MODE (declared_type))
-                      <= GET_MODE_SIZE (TYPE_MODE (passed_type))))
+         if (dmode == pmode)
            rtl = DECL_INCOMING_RTL (decl);
+         else if (SCALAR_INT_MODE_P (dmode)
+                  && GET_MODE_SIZE (dmode) <= GET_MODE_SIZE (pmode)
+                  && DECL_INCOMING_RTL (decl))
+           {
+             rtx inc = DECL_INCOMING_RTL (decl);
+             if (REG_P (inc))
+               rtl = inc;
+             else if (MEM_P (inc))
+               {
+                 if (BYTES_BIG_ENDIAN)
+                   rtl = adjust_address_nv (inc, dmode,
+                                            GET_MODE_SIZE (pmode)
+                                            - GET_MODE_SIZE (dmode));
+                 else
+                   rtl = inc;
+               }
+           }
        }
 
       /* If the parm was passed in registers, but lives on the stack, then
@@ -9332,13 +9865,13 @@ rtl_for_decl_location (tree decl)
         we reach the big endian correction code there.  It isn't clear if all
         of these checks are necessary here, but keeping them all is the safe
         thing to do.  */
-      else if (GET_CODE (rtl) == MEM
+      else if (MEM_P (rtl)
               && XEXP (rtl, 0) != const0_rtx
               && ! CONSTANT_P (XEXP (rtl, 0))
               /* Not passed in memory.  */
-              && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM
+              && !MEM_P (DECL_INCOMING_RTL (decl))
               /* Not passed by invisible reference.  */
-              && (GET_CODE (XEXP (rtl, 0)) != REG
+              && (!REG_P (XEXP (rtl, 0))
                   || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM
                   || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM
 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
@@ -9358,6 +9891,25 @@ rtl_for_decl_location (tree decl)
                             plus_constant (XEXP (rtl, 0), offset));
        }
     }
+  else if (TREE_CODE (decl) == VAR_DECL
+          && rtl
+          && MEM_P (rtl)
+          && GET_MODE (rtl) != TYPE_MODE (TREE_TYPE (decl))
+          && BYTES_BIG_ENDIAN)
+    {
+      int rsize = GET_MODE_SIZE (GET_MODE (rtl));
+      int dsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)));
+
+      /* If a variable is declared "register" yet is smaller than
+        a register, then if we store the variable to memory, it
+        looks like we're storing a register-sized value, when in
+        fact we are not.  We need to adjust the offset of the
+        storage location to reflect the actual value's bytes,
+        else gdb will not be able to display it.  */
+      if (rsize > dsize)
+       rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
+                          plus_constant (XEXP (rtl, 0), rsize-dsize));
+    }
 
   if (rtl != NULL_RTX)
     {
@@ -9391,7 +9943,8 @@ rtl_for_decl_location (tree decl)
                                   TREE_STRING_LENGTH (init) - 1) == 0
              && ((size_t) TREE_STRING_LENGTH (init)
                  == strlen (TREE_STRING_POINTER (init)) + 1))
-           rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init));
+           rtl = gen_rtx_CONST_STRING (VOIDmode,
+                                       ggc_strdup (TREE_STRING_POINTER (init)));
        }
       /* If the initializer is something that we know will expand into an
         immediate RTL constant, expand it now.  Expanding anything else
@@ -9402,13 +9955,12 @@ rtl_for_decl_location (tree decl)
          rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
                             EXPAND_INITIALIZER);
          /* If expand_expr returns a MEM, it wasn't immediate.  */
-         if (rtl && GET_CODE (rtl) == MEM)
-           abort ();
+         gcc_assert (!rtl || !MEM_P (rtl));
        }
     }
 
   if (rtl)
-    rtl = (*targetm.delegitimize_address) (rtl);
+    rtl = targetm.delegitimize_address (rtl);
 
   /* If we don't look past the constant pool, we risk emitting a
      reference to a constant pool entry that isn't referenced from
@@ -9419,6 +9971,29 @@ rtl_for_decl_location (tree decl)
   return rtl;
 }
 
+/* Return true if DECL's containing function has a frame base attribute.
+   Return false otherwise.  */
+
+static bool
+containing_function_has_frame_base (tree decl)
+{
+  tree declcontext = decl_function_context (decl);
+  dw_die_ref context;
+  dw_attr_ref attr;
+  
+  if (!declcontext)
+    return false;
+
+  context = lookup_decl_die (declcontext);
+  if (!context)
+    return false;
+
+  for (attr = context->die_attr; attr; attr = attr->dw_attr_next)
+    if (attr->dw_attr == DW_AT_frame_base)
+      return true;
+  return false;
+}
+  
 /* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value
    data attribute for a variable or a parameter.  We generate the
    DW_AT_const_value attribute only in those cases where the given variable
@@ -9431,86 +10006,143 @@ rtl_for_decl_location (tree decl)
    function call evaluates to a compile-time constant address.  */
 
 static void
-add_location_or_const_value_attribute (dw_die_ref die, tree decl)
+add_location_or_const_value_attribute (dw_die_ref die, tree decl,
+                                      enum dwarf_attribute attr)
 {
   rtx rtl;
   dw_loc_descr_ref descr;
-
+  var_loc_list *loc_list;
+  bool can_use_fb;
+  struct var_loc_node *node;
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
-  else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
-    abort ();
 
-  rtl = rtl_for_decl_location (decl);
-  if (rtl == NULL_RTX)
-    return;
+  gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
+             || TREE_CODE (decl) == RESULT_DECL);
+            
+  can_use_fb = containing_function_has_frame_base (decl);
 
-  switch (GET_CODE (rtl))
+  /* See if we possibly have multiple locations for this variable.  */
+  loc_list = lookup_decl_loc (decl);
+
+  /* If it truly has multiple locations, the first and last node will
+     differ.  */
+  if (loc_list && loc_list->first != loc_list->last)
     {
-    case ADDRESSOF:
-      /* The address of a variable that was optimized away;
-        don't emit anything.  */
-      break;
+      const char *secname;
+      const char *endname;
+      dw_loc_list_ref list;
+      rtx varloc;
 
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_STRING:
-    case SYMBOL_REF:
-    case LABEL_REF:
-    case CONST:
-    case PLUS:
-      /* DECL_RTL could be (plus (reg ...) (const_int ...)) */
-      add_const_value_attribute (die, rtl);
-      break;
 
-    case MEM:
-      if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+      /* We need to figure out what section we should use as the base
+        for the address ranges where a given location is valid.
+        1. If this particular DECL has a section associated with it,
+        use that.
+        2. If this function has a section associated with it, use
+        that.
+        3. Otherwise, use the text section.
+        XXX: If you split a variable across multiple sections, this
+        won't notice.  */
+
+      if (DECL_SECTION_NAME (decl))
        {
-         /* Need loc_descriptor_from_tree since that's where we know
-            how to handle TLS variables.  Want the object's address
-            since the top-level DW_AT_location assumes such.  See
-            the confusion in loc_descriptor for reference.  */
-         descr = loc_descriptor_from_tree (decl, 1);
+         tree sectree = DECL_SECTION_NAME (decl);
+         secname = TREE_STRING_POINTER (sectree);
        }
-      else
+      else if (current_function_decl
+              && DECL_SECTION_NAME (current_function_decl))
        {
-       case REG:
-       case SUBREG:
-       case CONCAT:
-         descr = loc_descriptor (rtl);
+         tree sectree = DECL_SECTION_NAME (current_function_decl);
+         secname = TREE_STRING_POINTER (sectree);
        }
-      add_AT_location_description (die, DW_AT_location, descr);
-      break;
+      else
+       secname = text_section_label;
+
+      /* Now that we know what section we are using for a base,
+         actually construct the list of locations.
+        The first location information is what is passed to the
+        function that creates the location list, and the remaining
+        locations just get added on to that list.
+        Note that we only know the start address for a location
+        (IE location changes), so to build the range, we use
+        the range [current location start, next location start].
+        This means we have to special case the last node, and generate
+        a range of [last location start, end of function label].  */
+
+      node = loc_list->first;
+      varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+      list = new_loc_list (loc_descriptor (varloc, can_use_fb),
+                          node->label, node->next->label, secname, 1);
+      node = node->next;
+
+      for (; node->next; node = node->next)
+       if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+         {
+           /* The variable has a location between NODE->LABEL and
+              NODE->NEXT->LABEL.  */
+           varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+           add_loc_descr_to_loc_list (&list,
+                                      loc_descriptor (varloc,
+                                                      can_use_fb),
+                                      node->label, node->next->label, secname);
+         }
 
-    case PARALLEL:
-      {
-       rtvec par_elems = XVEC (rtl, 0);
-       int num_elem = GET_NUM_ELEM (par_elems);
-       enum machine_mode mode;
-       int i;
+      /* If the variable has a location at the last label
+        it keeps its location until the end of function.  */
+      if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+       {
+         char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
 
-       /* Create the first one, so we have something to add to.  */
-       descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0));
-       mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
-       add_loc_descr (&descr,
-                      new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
-       for (i = 1; i < num_elem; i++)
-         {
-           dw_loc_descr_ref temp;
+         varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+         if (!current_function_decl)
+           endname = text_end_label;
+         else
+           {
+             ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+                                          current_function_funcdef_no);
+             endname = ggc_strdup (label_id);
+           }
+         add_loc_descr_to_loc_list (&list,
+                                    loc_descriptor (varloc,
+                                                    can_use_fb),
+                                    node->label, endname, secname);
+       }
 
-           temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0));
-           add_loc_descr (&descr, temp);
-           mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
-           add_loc_descr (&descr,
-                          new_loc_descr (DW_OP_piece,
-                                         GET_MODE_SIZE (mode), 0));
-         }
-      }
-      add_AT_location_description (die, DW_AT_location, descr);
-      break;
+      /* Finally, add the location list to the DIE, and we are done.  */
+      add_AT_loc_list (die, attr, list);
+      return;
+    }
 
-    default:
-      abort ();
+  /* Try to get some constant RTL for this decl, and use that as the value of
+     the location.  */
+  
+  rtl = rtl_for_decl_location (decl);
+  if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
+    {
+      add_const_value_attribute (die, rtl);
+      return;
+    }
+  
+  /* We couldn't get any rtl, and we had no >1 element location list, so try
+     directly generating the location description from the tree.  */
+  descr = loc_descriptor_from_tree (decl);
+  if (descr)
+    {
+      add_AT_location_description (die, attr, descr);
+      return;
+    }
+  
+  /* Lastly, if we have tried to generate the location otherwise, and it
+     didn't work out (we wouldn't be here if we did), and we have a one entry
+     location list, try generating a location from that.  */
+  if (loc_list && loc_list->first)
+    {
+      node = loc_list->first;
+      descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note), 
+                             can_use_fb);
+      if (descr)
+       add_AT_location_description (die, attr, descr);
     }
 }
 
@@ -9588,7 +10220,7 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
          || (bound_attr == DW_AT_lower_bound
              && (((is_c_family () || is_java ()) &&  integer_zerop (bound))
                  || (is_fortran () && integer_onep (bound)))))
-       /* use the default */
+       /* Use the default.  */
        ;
       else
        add_AT_unsigned (subrange_die, bound_attr, tree_low_cst (bound, 0));
@@ -9602,57 +10234,11 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
       break;
 
     case SAVE_EXPR:
-      /* If optimization is turned on, the SAVE_EXPRs that describe how to
-        access the upper bound values may be bogus.  If they refer to a
-        register, they may only describe how to get at these values at the
-        points in the generated code right after they have just been
-        computed.  Worse yet, in the typical case, the upper bound values
-        will not even *be* computed in the optimized code (though the
-        number of elements will), so these SAVE_EXPRs are entirely
-        bogus. In order to compensate for this fact, we check here to see
-        if optimization is enabled, and if so, we don't add an attribute
-        for the (unknown and unknowable) upper bound.  This should not
-        cause too much trouble for existing (stupid?)  debuggers because
-        they have to deal with empty upper bounds location descriptions
-        anyway in order to be able to deal with incomplete array types.
-        Of course an intelligent debugger (GDB?)  should be able to
-        comprehend that a missing upper bound specification in 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.
-
-        We assume that a MEM rtx is safe because gcc wouldn't put the
-        value there unless it was going to be used repeatedly in the
-        function, i.e. for cleanups.  */
-      if (SAVE_EXPR_RTL (bound)
-         && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
-       {
-         dw_die_ref ctx = lookup_decl_die (current_function_decl);
-         dw_die_ref decl_die = new_die (DW_TAG_variable, ctx, bound);
-         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.  */
-         if (GET_CODE (loc) == MEM)
-           {
-             rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound);
-
-             if (XEXP (loc, 0) != new_addr)
-               loc = gen_rtx_MEM (GET_MODE (loc), new_addr);
-           }
-
-         add_AT_flag (decl_die, DW_AT_artificial, 1);
-         add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
-         add_AT_location_description (decl_die, DW_AT_location,
-                                      loc_descriptor (loc));
-         add_AT_die_ref (subrange_die, bound_attr, decl_die);
-       }
-
-      /* Else leave out the attribute.  */
       break;
 
     case VAR_DECL:
     case PARM_DECL:
+    case RESULT_DECL:
       {
        dw_die_ref decl_die = lookup_decl_die (bound);
 
@@ -9674,7 +10260,7 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
        dw_die_ref ctx, decl_die;
        dw_loc_descr_ref loc;
 
-       loc = loc_descriptor_from_tree (bound, 0);
+       loc = loc_descriptor_from_tree (bound);
        if (loc == NULL)
          break;
 
@@ -9683,15 +10269,6 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
        else
          ctx = lookup_decl_die (current_function_decl);
 
-       /* If we weren't able to find a context, it's most likely the case
-          that we are processing the return type of the function.  So
-          make a SAVE_EXPR to point to it and have the limbo DIE code
-          find the proper die.  The save_expr function doesn't always
-          make a SAVE_EXPR, so do it ourselves.  */
-       if (ctx == 0)
-         bound = build (SAVE_EXPR, TREE_TYPE (bound), bound,
-                        current_function_decl, NULL_TREE);
-
        decl_die = new_die (DW_TAG_variable, ctx, bound);
        add_AT_flag (decl_die, DW_AT_artificial, 1);
        add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
@@ -9804,7 +10381,7 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
       size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Note that `size' might be -1 when we get to this point.  If it is, that
@@ -9841,9 +10418,7 @@ add_bit_offset_attribute (dw_die_ref die, tree decl)
   HOST_WIDE_INT unsigned bit_offset;
 
   /* Must be a field and a bit field.  */
-  if (!type
-      || TREE_CODE (decl) != FIELD_DECL)
-    abort ();
+  gcc_assert (type && TREE_CODE (decl) == FIELD_DECL);
 
   /* We can't yet handle bit-fields whose offsets are variable, so if we
      encounter such things, just return without generating any attribute
@@ -9883,9 +10458,8 @@ static inline void
 add_bit_size_attribute (dw_die_ref die, tree decl)
 {
   /* Must be a field and a bit field.  */
-  if (TREE_CODE (decl) != FIELD_DECL
-      || ! DECL_BIT_FIELD_TYPE (decl))
-    abort ();
+  gcc_assert (TREE_CODE (decl) == FIELD_DECL
+             && DECL_BIT_FIELD_TYPE (decl));
 
   if (host_integerp (DECL_SIZE (decl), 1))
     add_AT_unsigned (die, DW_AT_bit_size, tree_low_cst (DECL_SIZE (decl), 1));
@@ -9923,8 +10497,12 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
 
       if (TYPE_P (fn))
        fn = TYPE_STUB_DECL (fn);
+      
+      /* TYPE_STUB_DECL may have given us a NULL, which decl_function_context
+        won't like.  */
+      if (fn)  
+       fn = decl_function_context (fn);
 
-      fn = decl_function_context (fn);
       if (fn)
        dwarf2out_abstract_function (fn);
     }
@@ -9934,10 +10512,17 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
   else if (TYPE_P (origin))
     origin_die = lookup_type_die (origin);
 
-  if (origin_die == NULL)
-    abort ();
+  /* XXX: Functions that are never lowered don't always have correct block
+     trees (in the case of java, they simply have no block tree, in some other
+     languages).  For these functions, there is nothing we can really do to
+     output correct debug info for inlined functions in all cases.  Rather
+     than abort, we'll just produce deficient debug info now, in that we will
+     have variables without a proper abstract origin.  In the future, when all
+     functions are lowered, we should re-add a gcc_assert (origin_die)
+     here.  */
 
-  add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+  if (origin_die)
+      add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
 }
 
 /* We do not currently support the pure_virtual attribute.  */
@@ -9967,10 +10552,11 @@ add_pure_or_virtual_attribute (dw_die_ref die, tree func_decl)
 static void
 add_src_coords_attributes (dw_die_ref die, tree decl)
 {
-  unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
+  expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+  unsigned file_index = lookup_filename (s.file);
 
   add_AT_unsigned (die, DW_AT_decl_file, file_index);
-  add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
+  add_AT_unsigned (die, DW_AT_decl_line, s.line);
 }
 
 /* Add a DW_AT_name attribute and source coordinate attribute for the
@@ -10021,8 +10607,7 @@ push_decl_scope (tree scope)
 static inline void
 pop_decl_scope (void)
 {
-  if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0)
-    abort ();
+  gcc_assert (VARRAY_ACTIVE_SIZE (decl_scope_table) > 0);
 
   VARRAY_POP (decl_scope_table);
 }
@@ -10041,8 +10626,7 @@ scope_die_for (tree t, dw_die_ref context_die)
   int i;
 
   /* Non-types always go in the current scope.  */
-  if (! TYPE_P (t))
-    abort ();
+  gcc_assert (TYPE_P (t));
 
   containing_scope = TYPE_CONTEXT (t);
 
@@ -10074,9 +10658,8 @@ scope_die_for (tree t, dw_die_ref context_die)
 
       if (i < 0)
        {
-         if (debug_info_level > DINFO_LEVEL_TERSE
-             && !TREE_ASM_WRITTEN (containing_scope))
-           abort ();
+         gcc_assert (debug_info_level <= DINFO_LEVEL_TERSE
+                     || TREE_ASM_WRITTEN (containing_scope));
 
          /* If none of the current dies are suitable, we get file scope.  */
          scope_die = comp_unit_die;
@@ -10150,6 +10733,21 @@ add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
     add_AT_die_ref (object_die, DW_AT_type, type_die);
 }
 
+/* Given an object die, add the calling convention attribute for the
+   function call type.  */
+static void
+add_calling_convention_attribute (dw_die_ref subr_die, tree type)
+{
+  enum dwarf_calling_convention value = DW_CC_normal;
+
+  value = targetm.dwarf_calling_convention (type);
+
+  /* Only add the attribute if the backend requests it, and
+     is not DW_CC_normal.  */
+  if (value && (value != DW_CC_normal))
+    add_AT_unsigned (subr_die, DW_AT_calling_convention, value);
+}
+
 /* Given a tree pointer to a struct, class, union, or enum type node, return
    a pointer to the (string) tag name for the given type, or zero if the type
    was declared without a tag.  */
@@ -10203,12 +10801,10 @@ decl_start_label (tree decl)
   const char *fnname;
 
   x = DECL_RTL (decl);
-  if (GET_CODE (x) != MEM)
-    abort ();
+  gcc_assert (MEM_P (x));
 
   x = XEXP (x, 0);
-  if (GET_CODE (x) != SYMBOL_REF)
-    abort ();
+  gcc_assert (GET_CODE (x) == SYMBOL_REF);
 
   fnname = XSTR (x, 0);
   return fnname;
@@ -10282,16 +10878,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
   add_type_attribute (array_die, element_type, 0, 0, context_die);
 }
 
-static void
-gen_set_type_die (tree type, dw_die_ref context_die)
-{
-  dw_die_ref type_die
-    = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type);
-
-  equate_type_number_to_die (type, type_die);
-  add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die);
-}
-
 #if 0
 static void
 gen_entry_point_die (tree decl, dw_die_ref context_die)
@@ -10402,24 +10988,24 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
       if (type_die->die_parent == NULL)
        add_child_die (scope_die_for (type, context_die), type_die);
 
-      for (link = TYPE_FIELDS (type);
+      for (link = TYPE_VALUES (type);
           link != NULL; link = TREE_CHAIN (link))
        {
          dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link);
+         tree value = TREE_VALUE (link);
 
          add_name_attribute (enum_die,
                              IDENTIFIER_POINTER (TREE_PURPOSE (link)));
 
-         if (host_integerp (TREE_VALUE (link), 
-                            TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (link)))))
-           {
-             if (tree_int_cst_sgn (TREE_VALUE (link)) < 0)
-               add_AT_int (enum_die, DW_AT_const_value,
-                           tree_low_cst (TREE_VALUE (link), 0));
-             else
-               add_AT_unsigned (enum_die, DW_AT_const_value,
-                                tree_low_cst (TREE_VALUE (link), 1));
-           }
+         if (host_integerp (value, TYPE_UNSIGNED (TREE_TYPE (value))))
+           /* DWARF2 does not provide a way of indicating whether or
+              not enumeration constants are signed or unsigned.  GDB
+              always assumes the values are signed, so we output all
+              values as if they were signed.  That means that
+              enumeration constants with very large unsigned values
+              will appear to have negative values in the debugger.  */
+           add_AT_int (enum_die, DW_AT_const_value,
+                       tree_low_cst (value, tree_int_cst_sgn (value) > 0));
        }
     }
   else
@@ -10450,7 +11036,7 @@ gen_formal_parameter_die (tree node, dw_die_ref context_die)
 
   switch (TREE_CODE_CLASS (TREE_CODE (node)))
     {
-    case 'd':
+    case tcc_declaration:
       origin = decl_ultimate_origin (node);
       if (origin != NULL)
        add_abstract_origin_attribute (parm_die, origin);
@@ -10467,17 +11053,17 @@ gen_formal_parameter_die (tree node, dw_die_ref context_die)
 
       equate_decl_number_to_die (node, parm_die);
       if (! DECL_ABSTRACT (node))
-       add_location_or_const_value_attribute (parm_die, node);
+       add_location_or_const_value_attribute (parm_die, node, DW_AT_location);
 
       break;
 
-    case 't':
+    case tcc_type:
       /* We were called with some kind of a ..._TYPE node.  */
       add_type_attribute (parm_die, node, 0, 0, context_die);
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return parm_die;
@@ -10566,8 +11152,7 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
   if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))
       && ! lookup_decl_die (member))
     {
-      if (decl_ultimate_origin (member))
-       abort ();
+      gcc_assert (!decl_ultimate_origin (member));
 
       push_decl_scope (type);
       if (TREE_CODE (member) == FUNCTION_DECL)
@@ -10646,14 +11231,12 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
   if (origin && declaration && class_or_namespace_scope_p (context_die))
     {
       origin = NULL;
-      if (old_die)
-       abort ();
+      gcc_assert (!old_die);
     }
 
   if (origin != NULL)
     {
-      if (declaration && ! local_scope_p (context_die))
-       abort ();
+      gcc_assert (!declaration || local_scope_p (context_die));
 
       /* Fixup die_parent for the abstract instance of a nested
         inline function.  */
@@ -10665,7 +11248,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
     }
   else if (old_die)
     {
-      unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
+      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+      unsigned file_index = lookup_filename (s.file);
 
       if (!get_AT_flag (old_die, DW_AT_declaration)
          /* We can have a normal definition following an inline one in the
@@ -10673,14 +11257,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
             It seems reasonable to use AT_specification in this case.  */
          && !get_AT (old_die, DW_AT_inline))
        {
-         /* ??? This can happen if there is a bug in the program, for
-            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 an input error, not a dwarf2 bug.  */
-         if (errorcount)
-           return;
-         abort ();
+         /* Detect and ignore this case, where we are trying to output
+            something we have already output.  */
+         return;
        }
 
       /* If the definition comes from the same place as the declaration,
@@ -10694,13 +11273,17 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          && (DECL_ARTIFICIAL (decl)
              || (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
                  && (get_AT_unsigned (old_die, DW_AT_decl_line)
-                     == (unsigned) DECL_SOURCE_LINE (decl)))))
+                     == (unsigned) s.line))))
        {
          subr_die = old_die;
 
-         /* Clear out the declaration attribute and the parm types.  */
+         /* Clear out the declaration attribute and the formal parameters.
+            Do not remove all children, because it is possible that this
+            declaration die was forced using force_decl_die(). In such
+            cases die that forced declaration die (e.g. TAG_imported_module)
+            is one of the children that we do not want to remove.  */
          remove_AT (subr_die, DW_AT_declaration);
-         remove_children (subr_die);
+         remove_child_TAG (subr_die, DW_TAG_formal_parameter);
        }
       else
        {
@@ -10709,9 +11292,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
            add_AT_unsigned (subr_die, DW_AT_decl_file, file_index);
          if (get_AT_unsigned (old_die, DW_AT_decl_line)
-             != (unsigned) DECL_SOURCE_LINE (decl))
+             != (unsigned) s.line)
            add_AT_unsigned
-             (subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
+             (subr_die, DW_AT_decl_line, s.line);
        }
     }
   else
@@ -10748,8 +11331,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          /* The first time we see a member function, it is in the context of
             the class to which it belongs.  We make sure of this by emitting
             the class first.  The next time is the definition, which is
-            handled above.  The two may come from the same source text.  */
-         if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl))
+            handled above.  The two may come from the same source text.
+
+            Note that force_decl_die() forces function declaration die. It is
+            later reused to represent definition.  */
            equate_decl_number_to_die (decl, subr_die);
        }
     }
@@ -10795,17 +11380,21 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       /* Define the "frame base" location for this routine.  We use the
         frame pointer or stack pointer registers, since the RTL for local
         variables is relative to one of them.  */
-      fp_reg
-       = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
-      add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
+      if (frame_base_decl && lookup_decl_loc (frame_base_decl) != NULL)
+       {
+         add_location_or_const_value_attribute (subr_die, frame_base_decl,
+                                                DW_AT_frame_base);
+       }
+      else
+       {
+         fp_reg
+           = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
+         add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
+       }
 
-#if 0
-      /* ??? This fails for nested inline functions, because context_display
-        is not part of the state saved/restored for inline functions.  */
-      if (current_function_needs_context)
+      if (cfun->static_chain_decl)
        add_AT_location_description (subr_die, DW_AT_static_link,
-                            loc_descriptor (lookup_static_chain (decl)));
-#endif
+                loc_descriptor_from_tree (cfun->static_chain_decl));
     }
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -10881,6 +11470,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
      constructor function.  */
   if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK)
     {
+      /* Emit a DW_TAG_variable DIE for a named return value.  */
+      if (DECL_NAME (DECL_RESULT (decl)))
+       gen_decl_die (DECL_RESULT (decl), subr_die);
+
       current_function_has_inlines = 0;
       decls_for_scope (outer_scope, subr_die, 0);
 
@@ -10896,6 +11489,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        }
 #endif
     }
+  /* Add the calling convention attribute if requested.  */
+  add_calling_convention_attribute (subr_die, TREE_TYPE (decl));
+
 }
 
 /* Generate a DIE to represent a declared data object.  */
@@ -10928,16 +11524,16 @@ gen_variable_die (tree decl, dw_die_ref context_die)
       add_AT_specification (var_die, old_die);
       if (DECL_NAME (decl))
        {
-         unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
+         expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+         unsigned file_index = lookup_filename (s.file);
 
          if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
            add_AT_unsigned (var_die, DW_AT_decl_file, file_index);
 
          if (get_AT_unsigned (old_die, DW_AT_decl_line)
-             != (unsigned) DECL_SOURCE_LINE (decl))
+             != (unsigned) s.line)
 
-           add_AT_unsigned (var_die, DW_AT_decl_line,
-                            DECL_SOURCE_LINE (decl));
+           add_AT_unsigned (var_die, DW_AT_decl_line, s.line);
        }
     }
   else
@@ -10961,12 +11557,12 @@ gen_variable_die (tree decl, dw_die_ref context_die)
   if (declaration)
     add_AT_flag (var_die, DW_AT_declaration, 1);
 
-  if (class_or_namespace_scope_p (context_die) || DECL_ABSTRACT (decl))
+  if (DECL_ABSTRACT (decl) || declaration)
     equate_decl_number_to_die (decl, var_die);
 
   if (! declaration && ! DECL_ABSTRACT (decl))
     {
-      add_location_or_const_value_attribute (var_die, decl);
+      add_location_or_const_value_attribute (var_die, decl, DW_AT_location);
       add_pubname (decl, var_die);
     }
   else
@@ -10998,8 +11594,8 @@ gen_label_die (tree decl, dw_die_ref context_die)
         eliminated because of various optimizations.  We still emit them
         here so that it is possible to put breakpoints on them.  */
       if (insn
-         && (GET_CODE (insn) == CODE_LABEL
-             || ((GET_CODE (insn) == NOTE
+         && (LABEL_P (insn)
+             || ((NOTE_P (insn)
                   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))))
        {
          /* When optimization is enabled (via -O) some parts of the compiler
@@ -11007,8 +11603,7 @@ gen_label_die (tree decl, dw_die_ref context_die)
             represent source-level labels which were explicitly declared by
             the user.  This really shouldn't be happening though, so catch
             it if it ever does happen.  */
-         if (INSN_DELETED_P (insn))
-           abort ();
+         gcc_assert (!INSN_DELETED_P (insn));
 
          ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
          add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
@@ -11133,6 +11728,9 @@ gen_field_die (tree decl, dw_die_ref context_die)
     add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected);
   else if (TREE_PRIVATE (decl))
     add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private);
+
+  /* Equate decl number to die, so that we can look up this decl later on.  */
+  equate_decl_number_to_die (decl, decl_die);
 }
 
 #if 0
@@ -11225,6 +11823,8 @@ gen_compile_unit_die (const char *filename)
     language = DW_LANG_Ada95;
   else if (strcmp (language_string, "GNU F77") == 0)
     language = DW_LANG_Fortran77;
+  else if (strcmp (language_string, "GNU F95") == 0)
+    language = DW_LANG_Fortran95;
   else if (strcmp (language_string, "GNU Pascal") == 0)
     language = DW_LANG_Pascal83;
   else if (strcmp (language_string, "GNU Java") == 0)
@@ -11264,7 +11864,7 @@ gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die)
   add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
   add_data_member_location_attribute (die, binfo);
 
-  if (TREE_VIA_VIRTUAL (binfo))
+  if (BINFO_VIRTUAL_P (binfo))
     add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
 
   if (access == access_public_node)
@@ -11295,16 +11895,15 @@ gen_member_die (tree type, dw_die_ref context_die)
      the TREE node representing the appropriate (containing) type.  */
 
   /* First output info about the base classes.  */
-  if (binfo && BINFO_BASETYPES (binfo))
+  if (binfo)
     {
-      tree bases = BINFO_BASETYPES (binfo);
-      tree accesses = BINFO_BASEACCESSES (binfo);
-      int n_bases = TREE_VEC_LENGTH (bases);
+      VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo);
       int i;
+      tree base;
 
-      for (i = 0; i < n_bases; i++)
-       gen_inheritance_die (TREE_VEC_ELT (bases, i),
-                            (accesses ? TREE_VEC_ELT (accesses, i)
+      for (i = 0; BINFO_BASE_ITERATE (binfo, i, base); i++)
+       gen_inheritance_die (base,
+                            (accesses ? VEC_index (tree, accesses, i)
                              : access_public_node), context_die);
     }
 
@@ -11462,10 +12061,8 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = DECL_ORIGINAL_TYPE (decl);
 
-         if (type == TREE_TYPE (decl))
-           abort ();
-         else
-           equate_type_number_to_die (TREE_TYPE (decl), type_die);
+         gcc_assert (type != TREE_TYPE (decl));
+         equate_type_number_to_die (TREE_TYPE (decl), type_die);
        }
       else
        type = TREE_TYPE (decl);
@@ -11495,8 +12092,7 @@ gen_type_die (tree type, dw_die_ref context_die)
        return;
 
       /* Prevent broken recursion; we can't hand off to the same type.  */
-      if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type)
-       abort ();
+      gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
 
       TREE_ASM_WRITTEN (type) = 1;
       gen_decl_die (TYPE_NAME (type), context_die);
@@ -11546,14 +12142,10 @@ gen_type_die (tree type, dw_die_ref context_die)
       gen_ptr_to_mbr_type_die (type, context_die);
       break;
 
-    case SET_TYPE:
-      gen_type_die (TYPE_DOMAIN (type), context_die);
-      gen_set_type_die (type, context_die);
-      break;
-
     case FILE_TYPE:
       gen_type_die (TREE_TYPE (type), context_die);
-      abort ();                        /* No way to represent these in Dwarf yet!  */
+      /* No way to represent these in Dwarf yet!  */
+      gcc_unreachable ();
       break;
 
     case FUNCTION_TYPE:
@@ -11639,7 +12231,7 @@ gen_type_die (tree type, dw_die_ref context_die)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   TREE_ASM_WRITTEN (type) = 1;
@@ -11657,8 +12249,7 @@ gen_tagged_type_instantiation_die (tree type, dw_die_ref context_die)
      this type (i.e. without any const or volatile qualifiers) so make sure
      that we have the main variant (i.e. the unqualified version) of this
      type now.  */
-  if (type != type_main_variant (type))
-    abort ();
+  gcc_assert (type == type_main_variant (type));
 
   /* Do not check TREE_ASM_WRITTEN (type) as it may not be set if this is
      an instance of an unresolved type.  */
@@ -11682,7 +12273,7 @@ gen_tagged_type_instantiation_die (tree type, dw_die_ref context_die)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -11697,9 +12288,8 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
   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)))
+  /* Ignore blocks that are NULL.  */
+  if (stmt == NULL_TREE)
     return;
 
   /* If the block is one fragment of a non-contiguous block, do not
@@ -11745,7 +12335,10 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
          if (debug_info_level > DINFO_LEVEL_TERSE)
            /* We are not in terse mode so *any* local declaration counts
               as being a "significant" one.  */
-           must_output_die = (BLOCK_VARS (stmt) != NULL);
+           must_output_die = (BLOCK_VARS (stmt) != NULL 
+                              && (TREE_USED (stmt) 
+                                  || TREE_ASM_WRITTEN (stmt)
+                                  || BLOCK_ABSTRACT (stmt)));
          else
            /* We are in terse mode, so only local (nested) function
               definitions count as "significant" local declarations.  */
@@ -11787,29 +12380,32 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
   tree decl;
   tree subblocks;
 
-  /* Ignore blocks never really used to make RTL.  */
-  if (stmt == NULL_TREE || ! TREE_USED (stmt))
+  /* Ignore NULL blocks.  */
+  if (stmt == NULL_TREE)
     return;
 
-  /* Output the DIEs to represent all of the data objects and typedefs
-     declared directly within this block but not within any nested
-     sub-blocks.  Also, nested function and tag DIEs have been
-     generated with a parent of NULL; fix that up now.  */
-  for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
+  if (TREE_USED (stmt))
     {
-      dw_die_ref die;
-
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-       die = lookup_decl_die (decl);
-      else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
-       die = lookup_type_die (TREE_TYPE (decl));
-      else
-       die = NULL;
-
-      if (die != NULL && die->die_parent == NULL)
-       add_child_die (context_die, die);
-      else
-       gen_decl_die (decl, context_die);
+      /* Output the DIEs to represent all of the data objects and typedefs
+        declared directly within this block but not within any nested
+        sub-blocks.  Also, nested function and tag DIEs have been
+        generated with a parent of NULL; fix that up now.  */
+      for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
+       {
+         dw_die_ref die;
+         
+         if (TREE_CODE (decl) == FUNCTION_DECL)
+           die = lookup_decl_die (decl);
+         else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
+           die = lookup_type_die (TREE_TYPE (decl));
+         else
+           die = NULL;
+         
+         if (die != NULL && die->die_parent == NULL)
+           add_child_die (context_die, die);
+         else
+           gen_decl_die (decl, context_die);
+       }
     }
 
   /* If we're at -g1, we're not interested in subblocks.  */
@@ -11843,23 +12439,93 @@ is_redundant_typedef (tree decl)
   return 0;
 }
 
-/* Returns the DIE for namespace NS or aborts.
+/* Returns the DIE for decl or aborts.  */
 
-   Note that namespaces don't really have a lexical context, so there's no
-   need to pass in a context_die.  They always go inside their containing
-   namespace, or comp_unit_die if none.  */
+static dw_die_ref
+force_decl_die (tree decl)
+{
+  dw_die_ref decl_die;
+  unsigned saved_external_flag;
+  tree save_fn = NULL_TREE;
+  decl_die = lookup_decl_die (decl);
+  if (!decl_die)
+    {
+      dw_die_ref context_die;
+      tree decl_context = DECL_CONTEXT (decl);
+      if (decl_context)
+       {
+         /* Find die that represents this context.  */
+         if (TYPE_P (decl_context))
+           context_die = force_type_die (decl_context);
+         else
+           context_die = force_decl_die (decl_context);
+       }
+      else
+       context_die = comp_unit_die;
+
+      switch (TREE_CODE (decl))
+       {
+       case FUNCTION_DECL:
+         /* Clear current_function_decl, so that gen_subprogram_die thinks
+            that this is a declaration. At this point, we just want to force
+            declaration die.  */
+         save_fn = current_function_decl;
+         current_function_decl = NULL_TREE;
+         gen_subprogram_die (decl, context_die);
+         current_function_decl = save_fn;
+         break;
+
+       case VAR_DECL:
+         /* Set external flag to force declaration die. Restore it after
+          gen_decl_die() call.  */
+         saved_external_flag = DECL_EXTERNAL (decl);
+         DECL_EXTERNAL (decl) = 1;
+         gen_decl_die (decl, context_die);
+         DECL_EXTERNAL (decl) = saved_external_flag;
+         break;
+
+       case NAMESPACE_DECL:
+         dwarf2out_decl (decl);
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      /* See if we can find the die for this deci now.
+        If not then abort.  */
+      if (!decl_die)
+       decl_die = lookup_decl_die (decl);
+      gcc_assert (decl_die);
+    }
+
+  return decl_die;
+}
+
+/* Returns the DIE for decl or aborts.  */
 
 static dw_die_ref
-force_namespace_die (tree ns)
+force_type_die (tree type)
 {
-  dw_die_ref ns_die;
+  dw_die_ref type_die;
 
-  dwarf2out_decl (ns);
-  ns_die = lookup_decl_die (ns);
-  if (!ns_die)
-    abort();
+  type_die = lookup_type_die (type);
+  if (!type_die)
+    {
+      dw_die_ref context_die;
+      if (TYPE_CONTEXT (type))
+       if (TYPE_P (TYPE_CONTEXT (type)))
+         context_die = force_type_die (TYPE_CONTEXT (type));
+       else
+         context_die = force_decl_die (TYPE_CONTEXT (type));
+      else
+       context_die = comp_unit_die;
 
-  return ns_die;
+      gen_type_die (type, context_die);
+      type_die = lookup_type_die (type);
+      gcc_assert (type_die);
+    }
+  return type_die;
 }
 
 /* Force out any required namespaces to be able to output DECL,
@@ -11868,10 +12534,11 @@ force_namespace_die (tree ns)
 static dw_die_ref
 setup_namespace_context (tree thing, dw_die_ref context_die)
 {
-  tree context = DECL_P (thing) ? DECL_CONTEXT (thing) : TYPE_CONTEXT (thing);
+  tree context = (DECL_P (thing)
+                 ? DECL_CONTEXT (thing) : TYPE_CONTEXT (thing));
   if (context && TREE_CODE (context) == NAMESPACE_DECL)
     /* Force out the namespace.  */
-    context_die = force_namespace_die (context);
+    context_die = force_decl_die (context);
 
   return context_die;
 }
@@ -11890,6 +12557,12 @@ declare_in_namespace (tree thing, dw_die_ref context_die)
   if (debug_info_level <= DINFO_LEVEL_TERSE)
     return;
 
+  /* If this decl is from an inlined function, then don't try to emit it in its
+     namespace, as we will get confused.  It would have already been emitted
+     when the abstract instance of the inline function was emitted anyways.  */
+  if (DECL_P (thing) && DECL_ABSTRACT_ORIGIN (thing))
+    return;
+
   ns_context = setup_namespace_context (thing, context_die);
 
   if (ns_context != context_die)
@@ -11909,7 +12582,7 @@ gen_namespace_die (tree decl)
   dw_die_ref context_die = setup_namespace_context (decl, comp_unit_die);
 
   /* Namespace aliases have a DECL_ABSTRACT_ORIGIN of the namespace
-     they are an alias of. */
+     they are an alias of.  */
   if (DECL_ABSTRACT_ORIGIN (decl) == NULL)
     {
       /* Output a real namespace.  */
@@ -11924,7 +12597,7 @@ gen_namespace_die (tree decl)
 
       /* Force out the namespace we are an alias of, if necessary.  */
       dw_die_ref origin_die
-       = force_namespace_die (DECL_ABSTRACT_ORIGIN (decl));
+       = force_decl_die (DECL_ABSTRACT_ORIGIN (decl));
 
       /* Now create the namespace alias DIE.  */
       dw_die_ref namespace_die
@@ -11962,6 +12635,14 @@ gen_decl_die (tree decl, dw_die_ref context_die)
          && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl)))
        break;
 
+#if 0
+      /* FIXME */
+      /* This doesn't work because the C frontend sets DECL_ABSTRACT_ORIGIN
+        on local redeclarations of global functions.  That seems broken.  */
+      if (current_function_decl != decl)
+       /* This is only a declaration.  */;
+#endif
+
       /* If we're emitting a clone, emit info for the abstract instance.  */
       if (DECL_ORIGIN (decl) != decl)
        dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl));
@@ -12035,6 +12716,7 @@ gen_decl_die (tree decl, dw_die_ref context_die)
       break;
 
     case VAR_DECL:
+    case RESULT_DECL:
       /* If we are in terse mode, don't generate any DIEs to represent any
         variable declarations or definitions.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
@@ -12065,9 +12747,10 @@ gen_decl_die (tree decl, dw_die_ref context_die)
 
     case FIELD_DECL:
       /* Ignore the nameless fields that are used to skip bits but handle C++
-        anonymous unions.  */
+        anonymous unions and structs.  */
       if (DECL_NAME (decl) != NULL_TREE
-         || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
+         || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+         || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
        {
          gen_type_die (member_declared_type (decl), context_die);
          gen_field_die (decl, context_die);
@@ -12084,10 +12767,9 @@ gen_decl_die (tree decl, dw_die_ref context_die)
       break;
 
     default:
-      if ((int)TREE_CODE (decl) > NUM_TREE_CODES)
-       /* Probably some frontend-internal decl.  Assume we don't care.  */
-       break;
-      abort ();
+      /* Probably some frontend-internal decl.  Assume we don't care.  */
+      gcc_assert ((int)TREE_CODE (decl) > NUM_TREE_CODES);
+      break;
     }
 }
 \f
@@ -12127,6 +12809,62 @@ dwarf2out_global_decl (tree decl)
     dwarf2out_decl (decl);
 }
 
+/* Output debug information for type decl DECL.  Called from toplev.c
+   and from language front ends (to record built-in types).  */
+static void
+dwarf2out_type_decl (tree decl, int local)
+{
+  if (!local)
+    dwarf2out_decl (decl);
+}
+
+/* Output debug information for imported module or decl.  */
+
+static void
+dwarf2out_imported_module_or_decl (tree decl, tree context)
+{
+  dw_die_ref imported_die, at_import_die;
+  dw_die_ref scope_die;
+  unsigned file_index;
+  expanded_location xloc;
+
+  if (debug_info_level <= DINFO_LEVEL_TERSE)
+    return;
+
+  gcc_assert (decl);
+
+  /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
+     We need decl DIE for reference and scope die. First, get DIE for the decl
+     itself.  */
+
+  /* Get the scope die for decl context. Use comp_unit_die for global module
+     or decl. If die is not found for non globals, force new die.  */
+  if (!context)
+    scope_die = comp_unit_die;
+  else if (TYPE_P (context))
+    scope_die = force_type_die (context);
+  else
+    scope_die = force_decl_die (context);
+
+  /* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE.  */
+  if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
+    at_import_die = force_type_die (TREE_TYPE (decl));
+  else
+    at_import_die = force_decl_die (decl);
+
+  /* OK, now we have DIEs for decl as well as scope. Emit imported die.  */
+  if (TREE_CODE (decl) == NAMESPACE_DECL)
+    imported_die = new_die (DW_TAG_imported_module, scope_die, context);
+  else
+    imported_die = new_die (DW_TAG_imported_declaration, scope_die, context);
+
+  xloc = expand_location (input_location);
+  file_index = lookup_filename (xloc.file);
+  add_AT_unsigned (imported_die, DW_AT_decl_file, file_index);
+  add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line);
+  add_AT_die_ref (imported_die, DW_AT_import, at_import_die);
+}
+
 /* Write the debugging output for DECL.  */
 
 void
@@ -12140,12 +12878,6 @@ dwarf2out_decl (tree decl)
       return;
 
     case FUNCTION_DECL:
-      /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a
-        builtin function.  Explicit programmer-supplied declarations of
-        these same functions should NOT be ignored however.  */
-      if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl))
-       return;
-
       /* What we would really like to do here is to filter out all mere
         file-scope declarations of file-scope functions which are never
         referenced later within this translation unit (and keep all of ones
@@ -12217,7 +12949,7 @@ dwarf2out_decl (tree decl)
 
       /* Don't bother trying to generate any DIEs to represent any of the
         normal built-in types for the language we are compiling.  */
-      if (DECL_SOURCE_LINE (decl) == 0)
+      if (DECL_IS_BUILTIN (decl))
        {
          /* OK, we need to generate one for `bool' so GDB knows what type
             comparisons have.  */
@@ -12316,7 +13048,7 @@ lookup_filename (const char *file_name)
        return file_table_last_lookup_index;
     }
 
-  /* Didn't match the previous lookup, search the table */
+  /* Didn't match the previous lookup, search the table */
   n = VARRAY_ACTIVE_SIZE (file_table);
   for (i = 1; i < n; i++)
     if (strcmp (file_name, VARRAY_CHAR_PTR (file_table, i)) == 0)
@@ -12367,6 +13099,65 @@ init_file_table (void)
   file_table_last_lookup_index = 0;
 }
 
+/* Called by the final INSN scan whenever we see a var location.  We
+   use it to drop labels in the right places, and throw the location in
+   our lookup table.  */
+
+static void
+dwarf2out_var_location (rtx loc_note)
+{
+  char loclabel[MAX_ARTIFICIAL_LABEL_BYTES];
+  struct var_loc_node *newloc;
+  rtx prev_insn;
+  static rtx last_insn;
+  static const char *last_label;
+  tree decl;
+
+  if (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
+    return;
+  prev_insn = PREV_INSN (loc_note);
+
+  newloc = ggc_alloc_cleared (sizeof (struct var_loc_node));
+  /* If the insn we processed last time is the previous insn
+     and it is also a var location note, use the label we emitted
+     last time.  */
+  if (last_insn != NULL_RTX
+      && last_insn == prev_insn
+      && NOTE_P (prev_insn)
+      && NOTE_LINE_NUMBER (prev_insn) == NOTE_INSN_VAR_LOCATION)
+    {
+      newloc->label = last_label;
+    }
+  else
+    {
+      ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
+      ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
+      loclabel_num++;
+      newloc->label = ggc_strdup (loclabel);
+    }
+  newloc->var_loc_note = loc_note;
+  newloc->next = NULL;
+
+  last_insn = loc_note;
+  last_label = newloc->label;
+  decl = NOTE_VAR_LOCATION_DECL (loc_note);
+  if (DECL_DEBUG_EXPR (decl) && DECL_DEBUG_EXPR_IS_FROM (decl)
+      && DECL_P (DECL_DEBUG_EXPR (decl)))
+    decl = DECL_DEBUG_EXPR (decl); 
+  add_var_loc_to_decl (decl, newloc);
+}
+
+/* We need to reset the locations at the beginning of each
+   function. We can't do this in the end_function hook, because the
+   declarations that use the locations won't have been outputted when
+   that hook is called.  */
+
+static void
+dwarf2out_begin_function (tree unused ATTRIBUTE_UNUSED)
+{
+  htab_empty (decl_loc_table);
+}
+
 /* Output a label to mark the beginning of a source code line entry
    and record information relating to this source line, in
    'line_info_table' for later output of the .debug_line section.  */
@@ -12403,10 +13194,10 @@ dwarf2out_source_line (unsigned int line, const char *filename)
       else if (DECL_SECTION_NAME (current_function_decl))
        {
          dw_separate_line_info_ref line_info;
-         (*targetm.asm_out.internal_label) (asm_out_file, SEPARATE_LINE_CODE_LABEL,
+         targetm.asm_out.internal_label (asm_out_file, SEPARATE_LINE_CODE_LABEL,
                                     separate_line_info_table_in_use);
 
-         /* expand the line info table if necessary */
+         /* Expand the line info table if necessary.  */
          if (separate_line_info_table_in_use
              == separate_line_info_table_allocated)
            {
@@ -12433,7 +13224,7 @@ dwarf2out_source_line (unsigned int line, const char *filename)
        {
          dw_line_info_ref line_info;
 
-         (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
+         targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
                                     line_info_table_in_use);
 
          /* Expand the line info table if necessary.  */
@@ -12539,11 +13330,13 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 {
   init_file_table ();
 
-  /* Allocate the initial hunk of the decl_die_table.  */
-  decl_die_table = ggc_alloc_cleared (DECL_DIE_TABLE_INCREMENT
-                                     * sizeof (dw_die_ref));
-  decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
-  decl_die_table_in_use = 0;
+  /* Allocate the decl_die_table.  */
+  decl_die_table = htab_create_ggc (10, decl_die_table_hash,
+                                   decl_die_table_eq, NULL);
+
+  /* Allocate the decl_loc_table.  */
+  decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
+                                   decl_loc_table_eq, NULL);
 
   /* Allocate the initial hunk of the decl_scope_table.  */
   VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
@@ -12552,7 +13345,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT
                                        * sizeof (dw_die_ref));
   abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
-  /* Zero-th entry is allocated, but unused */
+  /* Zero-th entry is allocated, but unused */
   abbrev_die_table_in_use = 1;
 
   /* Allocate the initial hunk of the line_info_table.  */
@@ -12560,7 +13353,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
                                       * sizeof (dw_line_info_entry));
   line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
 
-  /* Zero-th entry is allocated, but unused */
+  /* Zero-th entry is allocated, but unused */
   line_info_table_in_use = 1;
 
   /* Generate the initial DIE for the .debug section.  Note that the (string)
@@ -12578,10 +13371,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_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_NAME));
+  ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
 
   ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
                               DEBUG_INFO_SECTION_LABEL, 0);
@@ -12604,11 +13394,8 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
     }
 
-  if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
-    {
-      text_section ();
-      ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
-    }
+  text_section ();
+  ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
 }
 
 /* A helper function for dwarf2out_finish called through
@@ -12773,8 +13560,8 @@ static void
 prune_unused_types_prune (dw_die_ref die)
 {
   dw_die_ref c, p, n;
-  if (!die->die_mark)
-    abort();
+
+  gcc_assert (die->die_mark);
 
   p = NULL;
   for (c = die->die_child; c; c = n)
@@ -12873,43 +13660,43 @@ dwarf2out_finish (const char *filename)
       if (die->die_parent == NULL)
        {
          dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
-         tree context;
 
          if (origin)
            add_child_die (origin->die_parent, die);
          else if (die == comp_unit_die)
            ;
-         /* If this was an expression for a bound involved in a function
-            return type, it may be a SAVE_EXPR for which we weren't able
-            to find a DIE previously.  So try now.  */
-         else if (node->created_for
-                  && TREE_CODE (node->created_for) == SAVE_EXPR
-                  && 0 != (origin = (lookup_decl_die
-                                     (SAVE_EXPR_CONTEXT
-                                      (node->created_for)))))
-           add_child_die (origin, 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 if (node->created_for
-                  && ((DECL_P (node->created_for)
-                       && (context = DECL_CONTEXT (node->created_for)))
-                      || (TYPE_P (node->created_for)
-                          && (context = TYPE_CONTEXT (node->created_for))))
-                  && TREE_CODE (context) == FUNCTION_DECL)
+         else
            {
              /* In certain situations, the lexical block containing a
                 nested function can be optimized away, which results
                 in the nested function die being orphaned.  Likewise
                 with the return type of that nested function.  Force
-                this to be a child of the containing function.  */
+                this to be a child of the containing function.
+
+                It may happen that even the containing function got fully
+                inlined and optimized out.  In that case we are lost and
+                assign the empty child.  This should not be big issue as
+                the function is likely unreachable too.  */
+             tree context = NULL_TREE;
+
+             gcc_assert (node->created_for);
+
+             if (DECL_P (node->created_for))
+               context = DECL_CONTEXT (node->created_for);
+             else if (TYPE_P (node->created_for))
+               context = TYPE_CONTEXT (node->created_for);
+
+             gcc_assert (context && TREE_CODE (context) == FUNCTION_DECL);
+
              origin = lookup_decl_die (context);
-             if (! origin)
-               abort ();
-             add_child_die (origin, die);
+             if (origin)
+               add_child_die (origin, die);
+             else
+               add_child_die (comp_unit_die, die);
            }
-         else
-           abort ();
        }
     }
 
@@ -12939,7 +13726,7 @@ dwarf2out_finish (const char *filename)
 
   /* Output a terminator label for the .text section.  */
   text_section ();
-  (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
+  targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
 
   /* Output the source line correspondence table.  We must do this
      even if there is no line information.  Otherwise, on an empty
@@ -13018,11 +13805,10 @@ dwarf2out_finish (const char *filename)
       output_ranges ();
     }
 
-  /* Have to end the primary source file.  */
+  /* Have to end the macro section.  */
   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");
       dw2_asm_output_data (1, 0, "End compilation unit");
     }