OSDN Git Service

* sourcebuild.texi (Config Fragments): Use @comma{} in
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 0bfe62c..f954b82 100644 (file)
@@ -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"
@@ -149,7 +150,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));
 }
 
@@ -243,6 +244,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;
@@ -357,7 +359,6 @@ 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 flush_queued_reg_saves (void);
 static bool clobbers_queued_reg_save (rtx);
 static void dwarf2out_frame_debug_expr (rtx, const char *);
@@ -391,7 +392,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"
@@ -809,9 +812,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
@@ -839,8 +840,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;
@@ -891,7 +891,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.
@@ -900,7 +900,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.
@@ -909,7 +909,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
@@ -918,7 +918,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))
@@ -970,7 +970,8 @@ initial_return_save (rtx rtl)
       abort ();
     }
 
-  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
@@ -997,7 +998,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);
@@ -1140,53 +1141,140 @@ 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)
+       {
+         if (i == ARRAY_SIZE (regs_saved_in_regs))
+           abort ();
+         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
@@ -1195,8 +1283,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
@@ -1220,12 +1308,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
@@ -1376,29 +1472,42 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
   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 if (call_used_regs [REGNO (dest)] 
+                  && ! fixed_regs [REGNO (dest)])
+           {
+             /* Saving a register in a register.  */
+             queue_reg_save (label, src, dest, 0);
+           }
          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;
          break;
 
        case PLUS:
@@ -1450,7 +1559,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
              if (! frame_pointer_needed)
                abort ();
 
-             if (GET_CODE (XEXP (src, 0)) == REG
+             if (REG_P (XEXP (src, 0))
                  && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg
                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
                {
@@ -1469,7 +1578,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
                abort ();
 
              /* 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)
                {
@@ -1484,7 +1593,7 @@ 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)
                {
@@ -1516,7 +1625,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
 
          /* Rule 7 */
        case IOR:
-         if (GET_CODE (XEXP (src, 0)) != REG
+         if (!REG_P (XEXP (src, 0))
              || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg
              || GET_CODE (XEXP (src, 1)) != CONST_INT)
            abort ();
@@ -1540,7 +1649,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
       break;
 
     case MEM:
-      if (GET_CODE (src) != REG)
+      if (!REG_P (src))
        abort ();
 
       /* Saving a register to the stack.  Make sure dest is relative to the
@@ -1638,7 +1747,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
@@ -1647,9 +1756,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)
+             if (!REG_P (x))
                abort ();
 
              cfa.reg = REGNO (x);
@@ -1661,7 +1770,7 @@ 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:
@@ -1681,6 +1790,8 @@ dwarf2out_frame_debug (rtx insn)
 
   if (insn == NULL_RTX)
     {
+      size_t i;
+      
       /* Flush any queued register saves.  */
       flush_queued_reg_saves ();
 
@@ -1693,6 +1804,13 @@ dwarf2out_frame_debug (rtx insn)
       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;
     }
 
@@ -1942,6 +2060,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_ONE_ONLY (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
@@ -1953,6 +2087,9 @@ 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_ONE_ONLY (fde_table[i].decl))
+         any_eh_needed = 1;
        else if (! fde_table[i].nothrow
                 && ! fde_table[i].all_throwers_are_sibcalls)
          any_eh_needed = true;
@@ -1966,7 +2103,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);
 
@@ -2004,7 +2141,9 @@ output_call_frame_info (int for_eh)
         P      Indicates the presence of an encoding + language
                personality routine in the CIE augmentation.  */
 
-      fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+      fde_encoding = TARGET_USES_WEAK_UNWIND_INFO
+       ? ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1)
+       : 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);
 
@@ -2057,7 +2196,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])
     {
@@ -2095,10 +2238,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_ONE_ONLY (fde->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,
@@ -2113,9 +2258,16 @@ output_call_frame_info (int for_eh)
 
       if (for_eh)
        {
-         dw2_asm_output_encoded_addr_rtx (fde_encoding,
-                  gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
-                  "FDE initial location");
+         if (TARGET_USES_WEAK_UNWIND_INFO
+             && DECL_ONE_ONLY (fde->decl))
+           dw2_asm_output_encoded_addr_rtx (fde_encoding,
+                    gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER
+                                                 (DECL_ASSEMBLER_NAME (fde->decl))),
+                    "FDE initial location");
+         else
+           dw2_asm_output_encoded_addr_rtx (fde_encoding,
+                    gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
+                    "FDE initial location");
          dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
                                fde->dw_fde_end, fde->dw_fde_begin,
                                "FDE address range");
@@ -2248,6 +2400,7 @@ 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->decl = current_function_decl;
   fde->dw_fde_begin = xstrdup (label);
   fde->dw_fde_current_label = NULL;
   fde->dw_fde_end = NULL;
@@ -2344,7 +2497,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,
@@ -2363,14 +2516,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.  */
@@ -2384,10 +2538,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;
@@ -3635,7 +3789,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 *);
@@ -3749,7 +3904,7 @@ 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);
@@ -3770,6 +3925,9 @@ 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,
                                                   enum dwarf_attribute);
@@ -3968,7 +4126,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));
 }
@@ -4605,16 +4763,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);
 }
 
@@ -5030,7 +5189,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.  */
@@ -5407,8 +5568,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));
@@ -5608,8 +5769,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);
@@ -5697,7 +5858,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;
@@ -5711,12 +5871,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;
@@ -6310,8 +6471,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;
@@ -6505,7 +6667,7 @@ value_format (dw_attr_ref a)
        }
     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;
@@ -6591,7 +6753,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);
 }
@@ -6774,16 +6936,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;
          }
 
@@ -6934,7 +7104,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.  */
@@ -7804,7 +7974,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;
@@ -7814,7 +7984,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;
@@ -7951,15 +8121,51 @@ is_subrange_type (tree type)
 {
   tree subtype = TREE_TYPE (type);
 
-  if (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)
-        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
@@ -7972,14 +8178,15 @@ subrange_type_die (tree type, dw_die_ref context_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);
 
@@ -7990,7 +8197,7 @@ subrange_type_die (tree type, dw_die_ref context_die)
       add_name_attribute (subrange_die, IDENTIFIER_POINTER (name));
     }
 
-  if (int_size_in_bytes (TREE_TYPE (type)) != size_in_bytes)
+  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.  */
@@ -8154,10 +8361,10 @@ 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);
 
@@ -8179,10 +8386,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
@@ -8211,8 +8418,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)
@@ -8320,7 +8527,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)));
 }
@@ -8349,13 +8556,14 @@ static dw_loc_descr_ref
 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))
     {
@@ -8392,7 +8600,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
         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, can_use_fbreg);
+       mem_loc_result = based_loc_descr (dbx_reg_number (rtl), 0,
+                                         can_use_fbreg);
       break;
 
     case MEM:
@@ -8463,7 +8672,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
     case PLUS:
     plus:
       if (is_based_loc (rtl))
-       mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
+       mem_loc_result = based_loc_descr (dbx_reg_number (XEXP (rtl, 0)),
                                          INTVAL (XEXP (rtl, 1)),
                                          can_use_fbreg);
       else
@@ -8489,10 +8698,26 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
        }
       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:
+      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:
       {
-       /* 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,
                                                   can_use_fbreg);
        dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
@@ -8503,7 +8728,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
 
        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;
       }
 
@@ -8511,15 +8736,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
       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,
-                                  can_use_fbreg);
-      else
-       return 0;
-
     default:
       abort ();
     }
@@ -8643,7 +8859,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
 {
   dw_loc_descr_ref ret, ret1;
   int indirect_p = 0;
-  int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
+  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
@@ -8655,7 +8871,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
@@ -8666,6 +8881,13 @@ 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.  */
@@ -8700,7 +8922,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))
@@ -8719,6 +8941,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
       /* Fall through.  */
 
     case PARM_DECL:
+    case RESULT_DECL:
       {
        rtx rtl = rtl_for_decl_location (loc);
 
@@ -8735,7 +8958,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
          {
            enum machine_mode mode = GET_MODE (rtl);
 
-           if (GET_CODE (rtl) == MEM)
+           if (MEM_P (rtl))
              {
                indirect_p = 1;
                rtl = XEXP (rtl, 0);
@@ -8817,12 +9040,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 (!MEM_P (rtl))
          return 0;
        mode = GET_MODE (rtl);
        rtl = XEXP (rtl, 0);
 
-       rtl = (*targetm.delegitimize_address) (rtl);
+       rtl = targetm.delegitimize_address (rtl);
 
        indirect_p = 1;
        ret = mem_loc_descriptor (rtl, mode, true);
@@ -8896,28 +9119,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;
@@ -8962,11 +9185,17 @@ loc_descriptor_from_tree (tree loc, int addressp)
       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 = build (COND_EXPR, TREE_TYPE (loc),
+                     build (code, integer_type_node,
+                            TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
+                     TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+      }
 
       /* ... fall through ...  */
 
@@ -9001,9 +9230,6 @@ loc_descriptor_from_tree (tree loc, int addressp)
       }
       break;
 
-    case EXPR_WITH_FILE_LOCATION:
-      return loc_descriptor_from_tree (EXPR_WFL_NODE (loc), addressp);
-
     default:
       /* Leave front-end specific codes as simply unknown.  This comes
         up, for instance, with the C STMT_EXPR.  */
@@ -9242,7 +9468,7 @@ 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 ())
@@ -9313,6 +9539,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
@@ -9345,14 +9621,11 @@ 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;
+           unsigned int length = GET_MODE_SIZE (mode);
+           unsigned char *array = ggc_alloc (length);
 
-           REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
-           real_to_target (array, &rv, mode);
-
-           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
          {
@@ -9366,6 +9639,68 @@ 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;
+
+       if (GET_MODE_CLASS (mode) == 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;
+               if (GET_CODE (elt) == CONST_INT)
+                 {
+                   lo = INTVAL (elt);
+                   hi = -(lo < 0);
+                 }
+               else if (GET_CODE (elt) == CONST_DOUBLE)
+                 {
+                   lo = CONST_DOUBLE_LOW (elt);
+                   hi = CONST_DOUBLE_HIGH (elt);
+                 }
+               else
+                 abort ();
+
+               if (elt_size <= sizeof (HOST_WIDE_INT))
+                 insert_int (lo, elt_size, p);
+               else if (elt_size == 2 * sizeof (HOST_WIDE_INT))
+                 {
+                   unsigned char *p0 = p;
+                   unsigned char *p1 = p + 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);
+                 }
+               else
+                 abort ();
+             }
+         }
+       else if (GET_MODE_CLASS (mode) == 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);
+             }
+         }
+       else
+         abort ();
+
+       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;
@@ -9471,10 +9806,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);
@@ -9486,13 +9818,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;
@@ -9523,13 +9855,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
@@ -9549,6 +9881,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)
     {
@@ -9593,13 +9944,13 @@ 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)
+         if (rtl && MEM_P (rtl))
            abort ();
        }
     }
 
   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
@@ -9631,7 +9982,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
-  else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
+  else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL
+          && TREE_CODE (decl) != RESULT_DECL)
     abort ();
 
   /* See if we possibly have multiple locations for this variable.  */
@@ -9732,13 +10084,9 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
 
   switch (GET_CODE (rtl))
     {
-    case ADDRESSOF:
-      /* The address of a variable that was optimized away;
-        don't emit anything.  */
-      break;
-
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case CONST_STRING:
     case SYMBOL_REF:
     case LABEL_REF:
@@ -9873,7 +10221,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));
@@ -9887,57 +10235,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, true));
-         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);
 
@@ -9968,15 +10270,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);
@@ -10252,10 +10545,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
@@ -10488,7 +10782,7 @@ decl_start_label (tree decl)
   const char *fnname;
 
   x = DECL_RTL (decl);
-  if (GET_CODE (x) != MEM)
+  if (!MEM_P (x))
     abort ();
 
   x = XEXP (x, 0);
@@ -10687,24 +10981,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
@@ -10950,7 +11244,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
@@ -10979,7 +11274,7 @@ 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;
 
@@ -10998,9 +11293,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
@@ -11098,13 +11393,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          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, 0));
     }
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -11180,6 +11471,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);
 
@@ -11227,16 +11522,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
@@ -11524,6 +11819,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)
@@ -12333,6 +12630,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));
@@ -12406,6 +12711,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)
@@ -12516,6 +12822,7 @@ 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;
@@ -12536,8 +12843,8 @@ dwarf2out_imported_module_or_decl (tree decl, tree context)
   else
     scope_die = force_decl_die (context);
 
-  /* For TYPE_DECL, lookup TREE_TYPE.  */
-  if (TREE_CODE (decl) == TYPE_DECL)
+  /* 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);
@@ -12547,10 +12854,11 @@ dwarf2out_imported_module_or_decl (tree decl, tree context)
     imported_die = new_die (DW_TAG_imported_module, scope_die, context);
   else
     imported_die = new_die (DW_TAG_imported_declaration, scope_die, context);
-  
-  file_index = lookup_filename (input_filename);
+
+  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, input_line);
+  add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line);
   add_AT_die_ref (imported_die, DW_AT_import, at_import_die);
 }
 
@@ -12638,7 +12946,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.  */
@@ -12879,10 +13187,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)
            {
@@ -12909,7 +13217,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.  */
@@ -13357,15 +13665,6 @@ dwarf2out_finish (const char *filename)
            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);
@@ -13417,7 +13716,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