OSDN Git Service

PR debug/44112
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index bd75de9..e68065b 100644 (file)
@@ -79,7 +79,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "dwarf2out.h"
 #include "dwarf2asm.h"
 #include "toplev.h"
-#include "varray.h"
 #include "ggc.h"
 #include "md5.h"
 #include "tm_p.h"
@@ -92,6 +91,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "input.h"
 #include "gimple.h"
 #include "tree-pass.h"
+#include "tree-flow.h"
 
 #ifdef DWARF2_DEBUGGING_INFO
 static void dwarf2out_source_line (unsigned int, const char *, int, bool);
@@ -1040,7 +1040,7 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p)
 
   cfi = new_cfi ();
 
-  if (loc.reg == old_cfa.reg && !loc.indirect)
+  if (loc.reg == old_cfa.reg && !loc.indirect && !old_cfa.indirect)
     {
       /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, indicating
         the CFA register did not change but the offset did.  The data
@@ -1056,7 +1056,8 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p)
 #ifndef MIPS_DEBUGGING_INFO  /* SGI dbx thinks this means no offset.  */
   else if (loc.offset == old_cfa.offset
           && old_cfa.reg != INVALID_REGNUM
-          && !loc.indirect)
+          && !loc.indirect
+          && !old_cfa.indirect)
     {
       /* Construct a "DW_CFA_def_cfa_register <register>" instruction,
         indicating the CFA register has changed to <register> but the
@@ -3051,7 +3052,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
     {
       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);
+                          "DW_CFA_offset, column %#lx", r);
       off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
       dw2_asm_output_data_uleb128 (off, NULL);
     }
@@ -3059,7 +3060,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
     {
       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);
+                          "DW_CFA_restore, column %#lx", r);
     }
   else
     {
@@ -3251,7 +3252,7 @@ output_cfi_directive (dw_cfi_ref cfi)
       break;
 
     case DW_CFA_GNU_args_size:
-      fprintf (asm_out_file, "\t.cfi_escape 0x%x,", DW_CFA_GNU_args_size);
+      fprintf (asm_out_file, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
       dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
       if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
@@ -3265,7 +3266,7 @@ output_cfi_directive (dw_cfi_ref cfi)
 
     case DW_CFA_def_cfa_expression:
     case DW_CFA_expression:
-      fprintf (asm_out_file, "\t.cfi_escape 0x%x,", cfi->dw_cfi_opc);
+      fprintf (asm_out_file, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
       output_cfa_loc_raw (cfi);
       fputc ('\n', asm_out_file);
       break;
@@ -3771,6 +3772,11 @@ output_call_frame_info (int for_eh)
     }
 
   dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation");
+  if (dw_cie_version >= 4)
+    {
+      dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "CIE Address Size");
+      dw2_asm_output_data (1, 0, "CIE Segment Size");
+    }
   dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor");
   dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT,
                               "CIE Data Alignment Factor");
@@ -3863,7 +3869,7 @@ dwarf2out_do_cfi_startproc (bool second)
       if (enc & DW_EH_PE_indirect)
        ref = dw2_force_const_mem (ref, true);
 
-      fprintf (asm_out_file, "\t.cfi_personality 0x%x,", enc);
+      fprintf (asm_out_file, "\t.cfi_personality %#x,", enc);
       output_addr_const (asm_out_file, ref);
       fputc ('\n', asm_out_file);
     }
@@ -3881,7 +3887,7 @@ dwarf2out_do_cfi_startproc (bool second)
       if (enc & DW_EH_PE_indirect)
        ref = dw2_force_const_mem (ref, true);
 
-      fprintf (asm_out_file, "\t.cfi_lsda 0x%x,", enc);
+      fprintf (asm_out_file, "\t.cfi_lsda %#x,", enc);
       output_addr_const (asm_out_file, ref);
       fputc ('\n', asm_out_file);
     }
@@ -4779,6 +4785,10 @@ size_of_loc_descr (dw_loc_descr_ref loc)
     case DW_OP_piece:
       size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
       break;
+    case DW_OP_bit_piece:
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      size += size_of_uleb128 (loc->dw_loc_oprnd2.v.val_unsigned);
+      break;
     case DW_OP_deref_size:
     case DW_OP_xderef_size:
       size += 1;
@@ -5003,6 +5013,10 @@ output_loc_operands (dw_loc_descr_ref loc)
     case DW_OP_piece:
       dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
       break;
+    case DW_OP_bit_piece:
+      dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
+      dw2_asm_output_data_uleb128 (val2->v.val_unsigned, NULL);
+      break;
     case DW_OP_deref_size:
     case DW_OP_xderef_size:
       dw2_asm_output_data (1, val1->v.val_int, NULL);
@@ -5118,6 +5132,12 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
       dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
       break;
 
+    case DW_OP_bit_piece:
+      fputc (',', asm_out_file);
+      dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
+      dw2_asm_output_data_uleb128_raw (val2->v.val_unsigned);
+      break;
+
     case DW_OP_consts:
     case DW_OP_breg0:
     case DW_OP_breg1:
@@ -5175,7 +5195,7 @@ output_loc_sequence_raw (dw_loc_descr_ref loc)
   while (1)
     {
       /* Output the opcode.  */
-      fprintf (asm_out_file, "0x%x", loc->dw_loc_opc);
+      fprintf (asm_out_file, "%#x", loc->dw_loc_opc);
       output_loc_operands_raw (loc);
 
       if (!loc->dw_loc_next)
@@ -5221,7 +5241,7 @@ output_cfa_loc_raw (dw_cfi_ref cfi)
 
   if (cfi->dw_cfi_opc == DW_CFA_expression)
     {
-      fprintf (asm_out_file, "0x%x,", cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+      fprintf (asm_out_file, "%#x,", cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
       loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
     }
   else
@@ -5410,6 +5430,7 @@ static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
 static void dwarf2out_start_source_file (unsigned, const char *);
 static void dwarf2out_end_source_file (unsigned);
+static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
@@ -5447,7 +5468,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_end_epilogue,
   dwarf2out_begin_function,
   debug_nothing_int,           /* end_function */
-  dwarf2out_decl,              /* function_decl */
+  dwarf2out_function_decl,     /* function_decl */
   dwarf2out_global_decl,
   dwarf2out_type_decl,         /* type_decl */
   dwarf2out_imported_module_or_decl,
@@ -5688,6 +5709,11 @@ skeleton_chain_node;
    is not made available by the GCC front-end.  */
 #define        DWARF_LINE_DEFAULT_IS_STMT_START 1
 
+/* Maximum number of operations per instruction bundle.  */
+#ifndef DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN
+#define DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN 1
+#endif
+
 #ifdef DWARF2_DEBUGGING_INFO
 /* This location is used by calc_die_sizes() to keep track
    the offset of each DIE within the .debug_info section.  */
@@ -5704,8 +5730,7 @@ static GTY(()) comdat_type_node *comdat_type_list;
 static GTY(()) limbo_die_node *limbo_die_list;
 
 /* A list of DIEs for which we may have to generate
-   DW_AT_MIPS_linkage_name once their DECL_ASSEMBLER_NAMEs are
-   set.  */
+   DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set.  */
 static GTY(()) limbo_die_node *deferred_asm_name;
 
 /* Filenames referenced by this compilation unit.  */
@@ -5729,9 +5754,16 @@ DEF_VEC_ALLOC_O(die_arg_entry,gc);
 
 /* Node of the variable location list.  */
 struct GTY ((chain_next ("%h.next"))) var_loc_node {
-  rtx GTY (()) var_loc_note;
+  /* Either NOTE_INSN_VAR_LOCATION, or, for SRA optimized variables,
+     EXPR_LIST chain.  For small bitsizes, bitsize is encoded
+     in mode of the EXPR_LIST node and first EXPR_LIST operand
+     is either NOTE_INSN_VAR_LOCATION for a piece with a known
+     location or NULL for padding.  For larger bitsizes,
+     mode is 0 and first operand is a CONCAT with bitsize
+     as first CONCAT operand and NOTE_INSN_VAR_LOCATION resp.
+     NULL as second operand.  */
+  rtx GTY (()) loc;
   const char * GTY (()) label;
-  const char * GTY (()) section_label;
   struct var_loc_node * GTY (()) next;
 };
 
@@ -5739,8 +5771,12 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node {
 struct GTY (()) var_loc_list_def {
   struct var_loc_node * GTY (()) first;
 
-  /* Do not mark the last element of the chained list because
-     it is marked through the chain.  */
+  /* Pointer to the last but one or last element of the
+     chained list.  If the list is empty, both first and
+     last are NULL, if the list contains just one node
+     or the last node certainly is not redundant, it points
+     to the last node, otherwise points to the last but one.
+     Do not mark it for GC because it is marked through the chain.  */
   struct var_loc_node * GTY ((skip ("%h"))) last;
 
   /* DECL_UID of the variable decl.  */
@@ -5964,9 +6000,7 @@ static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
 static int get_AT_flag (dw_die_ref, enum dwarf_attribute);
 static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
 static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
-static bool is_c_family (void);
 static bool is_cxx (void);
-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);
@@ -5984,7 +6018,7 @@ 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 (const_tree);
 static void equate_decl_number_to_die (tree, dw_die_ref);
-static struct var_loc_node *add_var_loc_to_decl (tree, rtx);
+static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *);
 static void print_spaces (FILE *);
 static void print_die (dw_die_ref, FILE *);
 static void print_dwarf_line_table (FILE *);
@@ -6105,6 +6139,7 @@ static void add_AT_location_description   (dw_die_ref, enum dwarf_attribute,
 static void add_data_member_location_attribute (dw_die_ref, tree);
 static bool add_const_value_attribute (dw_die_ref, rtx);
 static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
+static void insert_double (double_int, unsigned char *);
 static void insert_float (const_rtx, unsigned char *);
 static rtx rtl_for_decl_location (tree);
 static bool add_location_or_const_value_attribute (dw_die_ref, tree,
@@ -6270,6 +6305,12 @@ static void gen_remaining_tmpl_value_param_die_attribute (void);
 #define DEBUG_MACINFO_SECTION_LABEL     "Ldebug_macinfo"
 #endif
 
+/* Mangled name attribute to use.  This used to be a vendor extension
+   until DWARF 4 standardized it.  */
+#define AT_linkage_name \
+  (dwarf_version >= 4 ? DW_AT_linkage_name : DW_AT_MIPS_linkage_name)
+
+
 /* Definitions of defaults for formats and names of various special
    (artificial) labels which may be generated within this file (when the -g
    options is used and DWARF2_DEBUGGING_INFO is in effect.
@@ -7443,18 +7484,6 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind)
   return a ? AT_file (a) : NULL;
 }
 
-/* Return TRUE if the language is C or C++.  */
-
-static inline bool
-is_c_family (void)
-{
-  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
-
-  return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_ObjC
-         || lang == DW_LANG_C99
-         || lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus);
-}
-
 /* Return TRUE if the language is C++.  */
 
 static inline bool
@@ -7477,16 +7506,6 @@ is_fortran (void)
          || lang == DW_LANG_Fortran95);
 }
 
-/* Return TRUE if the language is Java.  */
-
-static inline bool
-is_java (void)
-{
-  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
-
-  return lang == DW_LANG_Java;
-}
-
 /* Return TRUE if the language is Ada.  */
 
 static inline bool
@@ -7761,16 +7780,175 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
   decl_die->decl_id = decl_id;
 }
 
+/* Return how many bits covers PIECE EXPR_LIST.  */
+
+static int
+decl_piece_bitsize (rtx piece)
+{
+  int ret = (int) GET_MODE (piece);
+  if (ret)
+    return ret;
+  gcc_assert (GET_CODE (XEXP (piece, 0)) == CONCAT
+             && CONST_INT_P (XEXP (XEXP (piece, 0), 0)));
+  return INTVAL (XEXP (XEXP (piece, 0), 0));
+}
+
+/* Return pointer to the location of location note in PIECE EXPR_LIST.  */
+
+static rtx *
+decl_piece_varloc_ptr (rtx piece)
+{
+  if ((int) GET_MODE (piece))
+    return &XEXP (piece, 0);
+  else
+    return &XEXP (XEXP (piece, 0), 1);
+}
+
+/* Create an EXPR_LIST for location note LOC_NOTE covering BITSIZE bits.
+   Next is the chain of following piece nodes.  */
+
+static rtx
+decl_piece_node (rtx loc_note, HOST_WIDE_INT bitsize, rtx next)
+{
+  if (bitsize <= (int) MAX_MACHINE_MODE)
+    return alloc_EXPR_LIST (bitsize, loc_note, next);
+  else
+    return alloc_EXPR_LIST (0, gen_rtx_CONCAT (VOIDmode,
+                                              GEN_INT (bitsize),
+                                              loc_note), next);
+}
+
+/* Return rtx that should be stored into loc field for
+   LOC_NOTE and BITPOS/BITSIZE.  */
+
+static rtx
+construct_piece_list (rtx loc_note, HOST_WIDE_INT bitpos,
+                     HOST_WIDE_INT bitsize)
+{
+  if (bitsize != -1)
+    {
+      loc_note = decl_piece_node (loc_note, bitsize, NULL_RTX);
+      if (bitpos != 0)
+       loc_note = decl_piece_node (NULL_RTX, bitpos, loc_note);
+    }
+  return loc_note;
+}
+
+/* This function either modifies location piece list *DEST in
+   place (if SRC and INNER is NULL), or copies location piece list
+   *SRC to *DEST while modifying it.  Location BITPOS is modified
+   to contain LOC_NOTE, any pieces overlapping it are removed resp.
+   not copied and if needed some padding around it is added.
+   When modifying in place, DEST should point to EXPR_LIST where
+   earlier pieces cover PIECE_BITPOS bits, when copying SRC points
+   to the start of the whole list and INNER points to the EXPR_LIST
+   where earlier pieces cover PIECE_BITPOS bits.  */
+
+static void
+adjust_piece_list (rtx *dest, rtx *src, rtx *inner,
+                  HOST_WIDE_INT bitpos, HOST_WIDE_INT piece_bitpos,
+                  HOST_WIDE_INT bitsize, rtx loc_note)
+{
+  int diff;
+  bool copy = inner != NULL;
+
+  if (copy)
+    {
+      /* First copy all nodes preceeding the current bitpos.  */
+      while (src != inner)
+       {
+         *dest = decl_piece_node (*decl_piece_varloc_ptr (*src),
+                                  decl_piece_bitsize (*src), NULL_RTX);
+         dest = &XEXP (*dest, 1);
+         src = &XEXP (*src, 1);
+       }
+    }
+  /* Add padding if needed.  */
+  if (bitpos != piece_bitpos)
+    {
+      *dest = decl_piece_node (NULL_RTX, bitpos - piece_bitpos,
+                              copy ? NULL_RTX : *dest);
+      dest = &XEXP (*dest, 1);
+    }
+  else if (*dest && decl_piece_bitsize (*dest) == bitsize)
+    {
+      gcc_assert (!copy);
+      /* A piece with correct bitpos and bitsize already exist,
+        just update the location for it and return.  */
+      *decl_piece_varloc_ptr (*dest) = loc_note;
+      return;
+    }
+  /* Add the piece that changed.  */
+  *dest = decl_piece_node (loc_note, bitsize, copy ? NULL_RTX : *dest);
+  dest = &XEXP (*dest, 1);
+  /* Skip over pieces that overlap it.  */
+  diff = bitpos - piece_bitpos + bitsize;
+  if (!copy)
+    src = dest;
+  while (diff > 0 && *src)
+    {
+      rtx piece = *src;
+      diff -= decl_piece_bitsize (piece);
+      if (copy)
+       src = &XEXP (piece, 1);
+      else
+       {
+         *src = XEXP (piece, 1);
+         free_EXPR_LIST_node (piece);
+       }
+    }
+  /* Add padding if needed.  */
+  if (diff < 0 && *src)
+    {
+      if (!copy)
+       dest = src;
+      *dest = decl_piece_node (NULL_RTX, -diff, copy ? NULL_RTX : *dest);
+      dest = &XEXP (*dest, 1);
+    }
+  if (!copy)
+    return;
+  /* Finally copy all nodes following it.  */
+  while (*src)
+    {
+      *dest = decl_piece_node (*decl_piece_varloc_ptr (*src),
+                              decl_piece_bitsize (*src), NULL_RTX);
+      dest = &XEXP (*dest, 1);
+      src = &XEXP (*src, 1);
+    }
+}
+
 /* Add a variable location node to the linked list for DECL.  */
 
 static struct var_loc_node *
-add_var_loc_to_decl (tree decl, rtx loc_note)
+add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
 {
-  unsigned int decl_id = DECL_UID (decl);
+  unsigned int decl_id;
   var_loc_list *temp;
   void **slot;
   struct var_loc_node *loc = NULL;
+  HOST_WIDE_INT bitsize = -1, bitpos = -1;
 
+  if (DECL_DEBUG_EXPR_IS_FROM (decl))
+    {
+      tree realdecl = DECL_DEBUG_EXPR (decl);
+      if (realdecl && handled_component_p (realdecl))
+       {
+         HOST_WIDE_INT maxsize;
+         tree innerdecl;
+         innerdecl
+           = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
+         if (!DECL_P (innerdecl)
+             || DECL_IGNORED_P (innerdecl)
+             || TREE_STATIC (innerdecl)
+             || bitsize <= 0
+             || bitpos + bitsize > 256
+             || bitsize != maxsize)
+           return NULL;
+         decl = innerdecl;
+       }
+    }
+
+  decl_id = DECL_UID (decl);
   slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
   if (*slot == NULL)
     {
@@ -7783,29 +7961,108 @@ add_var_loc_to_decl (tree decl, rtx loc_note)
 
   if (temp->last)
     {
+      struct var_loc_node *last = temp->last, *unused = NULL;
+      rtx *piece_loc = NULL, last_loc_note;
+      int piece_bitpos = 0;
+      if (last->next)
+       {
+         last = last->next;
+         gcc_assert (last->next == NULL);
+       }
+      if (bitsize != -1 && GET_CODE (last->loc) == EXPR_LIST)
+       {
+         piece_loc = &last->loc;
+         do
+           {
+             int cur_bitsize = decl_piece_bitsize (*piece_loc);
+             if (piece_bitpos + cur_bitsize > bitpos)
+               break;
+             piece_bitpos += cur_bitsize;
+             piece_loc = &XEXP (*piece_loc, 1);
+           }
+         while (*piece_loc);
+       }
+      /* TEMP->LAST here is either pointer to the last but one or
+        last element in the chained list, LAST is pointer to the
+        last element.  */
+      if (label && strcmp (last->label, label) == 0)
+       {
+         /* For SRA optimized variables if there weren't any real
+            insns since last note, just modify the last node.  */
+         if (piece_loc != NULL)
+           {
+             adjust_piece_list (piece_loc, NULL, NULL,
+                                bitpos, piece_bitpos, bitsize, loc_note);
+             return NULL;
+           }
+         /* If the last note doesn't cover any instructions, remove it.  */
+         if (temp->last != last)
+           {
+             temp->last->next = NULL;
+             unused = last;
+             last = temp->last;
+             gcc_assert (strcmp (last->label, label) != 0);
+           }
+         else
+           {
+             gcc_assert (temp->first == temp->last);
+             memset (temp->last, '\0', sizeof (*temp->last));
+             temp->last->loc = construct_piece_list (loc_note, bitpos, bitsize);
+             return temp->last;
+           }
+       }
+      if (bitsize == -1 && NOTE_P (last->loc))
+       last_loc_note = last->loc;
+      else if (piece_loc != NULL
+              && *piece_loc != NULL_RTX
+              && piece_bitpos == bitpos
+              && decl_piece_bitsize (*piece_loc) == bitsize)
+       last_loc_note = *decl_piece_varloc_ptr (*piece_loc);
+      else
+       last_loc_note = NULL_RTX;
       /* If the current location is the same as the end of the list,
         and either both or neither of the locations is uninitialized,
         we have nothing to do.  */
-      if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
-                        NOTE_VAR_LOCATION_LOC (loc_note)))
-         || ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
+      if (last_loc_note == NULL_RTX
+         || (!rtx_equal_p (NOTE_VAR_LOCATION_LOC (last_loc_note),
+                           NOTE_VAR_LOCATION_LOC (loc_note)))
+         || ((NOTE_VAR_LOCATION_STATUS (last_loc_note)
               != NOTE_VAR_LOCATION_STATUS (loc_note))
-             && ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
+             && ((NOTE_VAR_LOCATION_STATUS (last_loc_note)
                   == VAR_INIT_STATUS_UNINITIALIZED)
                  || (NOTE_VAR_LOCATION_STATUS (loc_note)
                      == VAR_INIT_STATUS_UNINITIALIZED))))
        {
-         /* Add LOC to the end of list and update LAST.  */
-         loc = GGC_CNEW (struct var_loc_node);
-         temp->last->next = loc;
-         temp->last = loc;
+         /* Add LOC to the end of list and update LAST.  If the last
+            element of the list has been removed above, reuse its
+            memory for the new node, otherwise allocate a new one.  */
+         if (unused)
+           {
+             loc = unused;
+             memset (loc, '\0', sizeof (*loc));
+           }
+         else
+           loc = GGC_CNEW (struct var_loc_node);
+         if (bitsize == -1 || piece_loc == NULL)
+           loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
+         else
+           adjust_piece_list (&loc->loc, &last->loc, piece_loc,
+                              bitpos, piece_bitpos, bitsize, loc_note);
+         last->next = loc;
+         /* Ensure TEMP->LAST will point either to the new last but one
+            element of the chain, or to the last element in it.  */
+         if (last != temp->last)
+           temp->last = last;
        }
+      else if (unused)
+       ggc_free (unused);
     }
   else
     {
       loc = GGC_CNEW (struct var_loc_node);
       temp->first = loc;
       temp->last = loc;
+      loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
     }
   return loc;
 }
@@ -8264,6 +8521,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
       if ((at->dw_attr == DW_AT_type
           && (tag == DW_TAG_pointer_type
               || tag == DW_TAG_reference_type
+              || tag == DW_TAG_rvalue_reference_type
               || tag == DW_TAG_ptr_to_member_type))
          || (at->dw_attr == DW_AT_friend
              && tag == DW_TAG_friend))
@@ -8978,6 +9236,7 @@ is_type_die (dw_die_ref die)
     case DW_TAG_enumeration_type:
     case DW_TAG_pointer_type:
     case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
     case DW_TAG_string_type:
     case DW_TAG_structure_type:
     case DW_TAG_subroutine_type:
@@ -9015,6 +9274,7 @@ is_comdat_die (dw_die_ref c)
 
   if (c->die_tag == DW_TAG_pointer_type
       || c->die_tag == DW_TAG_reference_type
+      || c->die_tag == DW_TAG_rvalue_reference_type
       || c->die_tag == DW_TAG_const_type
       || c->die_tag == DW_TAG_volatile_type)
     {
@@ -9263,6 +9523,7 @@ should_move_die_to_comdat (dw_die_ref die)
     case DW_TAG_interface_type:
     case DW_TAG_pointer_type:
     case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
     case DW_TAG_string_type:
     case DW_TAG_subroutine_type:
     case DW_TAG_ptr_to_member_type:
@@ -9346,6 +9607,7 @@ clone_as_declaration (dw_die_ref die)
         case DW_AT_name:
         case DW_AT_type:
         case DW_AT_virtuality:
+        case DW_AT_linkage_name:
         case DW_AT_MIPS_linkage_name:
           add_dwarf_attr (clone, a);
           break;
@@ -9920,7 +10182,10 @@ size_of_die (dw_die_ref die)
            unsigned long lsize = size_of_locs (AT_loc (a));
 
            /* Block length.  */
-           size += constant_size (lsize);
+           if (dwarf_version >= 4)
+             size += size_of_uleb128 (lsize);
+           else
+             size += constant_size (lsize);
            size += lsize;
          }
          break;
@@ -9948,7 +10213,16 @@ size_of_die (dw_die_ref die)
                    * a->dw_attr_val.v.val_vec.elt_size; /* block */
          break;
        case dw_val_class_flag:
-         size += 1;
+         if (dwarf_version >= 4)
+           /* Currently all add_AT_flag calls pass in 1 as last argument,
+              so DW_FORM_flag_present can be used.  If that ever changes,
+              we'll need to use DW_FORM_flag and have some optimization
+              in build_abbrev_table that will change those to
+              DW_FORM_flag_present if it is set to 1 in all DIEs using
+              the same abbrev entry.  */
+           gcc_assert (a->dw_attr_val.v.val_flag == 1);
+         else
+           size += 1;
          break;
        case dw_val_class_die_ref:
          if (AT_ref_external (a))
@@ -10142,8 +10416,11 @@ value_format (dw_attr_ref a)
          gcc_unreachable ();
        }
     case dw_val_class_range_list:
-    case dw_val_class_offset:
     case dw_val_class_loc_list:
+      if (dwarf_version >= 4)
+       return DW_FORM_sec_offset;
+      /* FALLTHRU */
+    case dw_val_class_offset:
       switch (DWARF_OFFSET_SIZE)
        {
        case 4:
@@ -10154,6 +10431,8 @@ value_format (dw_attr_ref a)
          gcc_unreachable ();
        }
     case dw_val_class_loc:
+      if (dwarf_version >= 4)
+       return DW_FORM_exprloc;
       switch (constant_size (size_of_locs (AT_loc (a))))
        {
        case 1:
@@ -10206,6 +10485,17 @@ value_format (dw_attr_ref a)
          gcc_unreachable ();
        }
     case dw_val_class_flag:
+      if (dwarf_version >= 4)
+       {
+         /* Currently all add_AT_flag calls pass in 1 as last argument,
+            so DW_FORM_flag_present can be used.  If that ever changes,
+            we'll need to use DW_FORM_flag and have some optimization
+            in build_abbrev_table that will change those to
+            DW_FORM_flag_present if it is set to 1 in all DIEs using
+            the same abbrev entry.  */
+         gcc_assert (a->dw_attr_val.v.val_flag == 1);
+         return DW_FORM_flag_present;
+       }
       return DW_FORM_flag;
     case dw_val_class_die_ref:
       if (AT_ref_external (a))
@@ -10218,7 +10508,7 @@ value_format (dw_attr_ref a)
       return DW_FORM_addr;
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
-      return DW_FORM_data;
+      return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data;
     case dw_val_class_str:
       return AT_string_form (a);
     case dw_val_class_file:
@@ -10415,7 +10705,7 @@ output_die (dw_die_ref die)
   if (dwarf_version < 4 && die->die_id.die_symbol)
     output_die_symbol (die);
 
-  dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)",
+  dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
                               (unsigned long)die->die_offset,
                               dwarf_tag_name (die->die_tag));
 
@@ -10450,7 +10740,10 @@ output_die (dw_die_ref die)
          size = size_of_locs (AT_loc (a));
 
          /* Output the block length for this list of location operations.  */
-         dw2_asm_output_data (constant_size (size), size, "%s", name);
+         if (dwarf_version >= 4)
+           dw2_asm_output_data_uleb128 (size, "%s", name);
+         else
+           dw2_asm_output_data (constant_size (size), size, "%s", name);
 
          output_loc_sequence (AT_loc (a));
          break;
@@ -10518,6 +10811,20 @@ output_die (dw_die_ref die)
          }
 
        case dw_val_class_flag:
+         if (dwarf_version >= 4)
+           {
+             /* Currently all add_AT_flag calls pass in 1 as last argument,
+                so DW_FORM_flag_present can be used.  If that ever changes,
+                we'll need to use DW_FORM_flag and have some optimization
+                in build_abbrev_table that will change those to
+                DW_FORM_flag_present if it is set to 1 in all DIEs using
+                the same abbrev entry.  */
+             gcc_assert (AT_flag (a) == 1);
+             if (flag_debug_asm)
+               fprintf (asm_out_file, "\t\t\t%s %s\n",
+                        ASM_COMMENT_START, name);
+             break;
+           }
          dw2_asm_output_data (1, AT_flag (a), "%s", name);
          break;
 
@@ -10630,7 +10937,7 @@ output_die (dw_die_ref die)
 
   /* Add null byte to terminate sibling list.  */
   if (die->die_child != NULL)
-    dw2_asm_output_data (1, 0, "end of children of DIE 0x%lx",
+    dw2_asm_output_data (1, 0, "end of children of DIE %#lx",
                         (unsigned long) die->die_offset);
 }
 
@@ -10642,11 +10949,6 @@ output_compilation_unit_header (void)
 {
   int ver = dwarf_version;
 
-  /* Don't mark the output as DWARF-4 until we make full use of the
-     version 4 extensions, and gdb supports them.  For now, -gdwarf-4
-     selects only a few extensions from the DWARF-4 spec.  */
-  if (ver > 3)
-    ver = 3;
   if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
     dw2_asm_output_data (4, 0xffffffff,
       "Initial length escape value indicating 64-bit DWARF extension");
@@ -11061,7 +11363,7 @@ static void
 output_ranges (void)
 {
   unsigned i;
-  static const char *const start_fmt = "Offset 0x%x";
+  static const char *const start_fmt = "Offset %#x";
   const char *fmt = start_fmt;
 
   for (i = 0; i < ranges_table_in_use; i++)
@@ -11403,7 +11705,7 @@ output_file_names (void)
     dw2_asm_output_nstring (dirs[i].path,
                            dirs[i].length
                             - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR,
-                           "Directory Entry: 0x%x", i + idx_offset);
+                           "Directory Entry: %#x", i + idx_offset);
 
   dw2_asm_output_data (1, 0, "End directory table");
 
@@ -11439,7 +11741,7 @@ output_file_names (void)
                files[file_idx].path + dirs[dir_idx].length, ver);
 
       dw2_asm_output_nstring
-       (filebuf, -1, "File Entry: 0x%x", (unsigned) i + 1);
+       (filebuf, -1, "File Entry: %#x", (unsigned) i + 1);
 
       /* Include directory index.  */
       dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
@@ -11457,7 +11759,7 @@ output_file_names (void)
         NULL);
 #else
       dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1,
-                             "File Entry: 0x%x", (unsigned) i + 1);
+                             "File Entry: %#x", (unsigned) i + 1);
 
       /* Include directory index.  */
       dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
@@ -11493,12 +11795,6 @@ output_line_info (void)
   unsigned long function;
   int ver = dwarf_version;
 
-  /* Don't mark the output as DWARF-4 until we make full use of the
-     version 4 extensions, and gdb supports them.  For now, -gdwarf-4
-     selects only a few extensions from the DWARF-4 spec.  */
-  if (ver > 3)
-    ver = 3;
-
   ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0);
@@ -11526,6 +11822,9 @@ output_line_info (void)
   dw2_asm_output_data (1, 1,
                       "Minimum Instruction Length");
 
+  if (ver >= 4)
+    dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN,
+                        "Maximum Operations Per Instruction");
   dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
                       "Default is_stmt_start flag");
   dw2_asm_output_data (1, DWARF_LINE_BASE,
@@ -11551,7 +11850,7 @@ output_line_info (void)
          break;
        }
 
-      dw2_asm_output_data (1, n_op_args, "opcode: 0x%x has %d args",
+      dw2_asm_output_data (1, n_op_args, "opcode: %#x has %d args",
                           opc, n_op_args);
     }
 
@@ -11996,10 +12295,6 @@ base_type_die (tree type)
 
   base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type);
 
-  /* This probably indicates a bug.  */
-  if (! TYPE_NAME (type))
-    add_name_attribute (base_type_result, "__unknown__");
-
   add_AT_unsigned (base_type_result, DW_AT_byte_size,
                   int_size_in_bytes (type));
   add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
@@ -12117,6 +12412,21 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
                          ((is_const_type ? TYPE_QUAL_CONST : 0)
                           | (is_volatile_type ? TYPE_QUAL_VOLATILE : 0)));
 
+  if (qualified_type == sizetype
+      && TYPE_NAME (qualified_type)
+      && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL)
+    {
+#ifdef ENABLE_CHECKING
+      gcc_assert (TREE_CODE (TREE_TYPE (TYPE_NAME (qualified_type)))
+                 == INTEGER_TYPE
+                 && TYPE_PRECISION (TREE_TYPE (TYPE_NAME (qualified_type)))
+                    == TYPE_PRECISION (qualified_type)
+                 && TYPE_UNSIGNED (TREE_TYPE (TYPE_NAME (qualified_type)))
+                    == TYPE_UNSIGNED (qualified_type));
+#endif
+      qualified_type = TREE_TYPE (TYPE_NAME (qualified_type));
+    }
+
   /* If we do, then we can just use its DIE, if it exists.  */
   if (qualified_type)
     {
@@ -12128,7 +12438,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
   name = qualified_type ? TYPE_NAME (qualified_type) : NULL;
 
   /* Handle C typedef types.  */
-  if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name))
+  if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name)
+      && !DECL_ARTIFICIAL (name))
     {
       tree dtype = TREE_TYPE (name);
 
@@ -12173,7 +12484,11 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
     }
   else if (code == REFERENCE_TYPE)
     {
-      mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
+      if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
+       mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die,
+                               type);
+      else
+       mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
       add_AT_unsigned (mod_type_die, DW_AT_byte_size,
                       simple_type_size_in_bits (type) / BITS_PER_UNIT);
       item_type = TREE_TYPE (type);
@@ -12228,6 +12543,9 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
        name = DECL_NAME (name);
       add_name_attribute (mod_type_die, IDENTIFIER_POINTER (name));
     }
+  /* This probably indicates a bug.  */
+  else if (mod_type_die && mod_type_die->die_tag == DW_TAG_base_type)
+    add_name_attribute (mod_type_die, "__unknown__");
 
   if (qualified_type)
     equate_type_number_to_die (qualified_type, mod_type_die);
@@ -13731,10 +14049,12 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
 
     case VAR_LOCATION:
       /* Single part.  */
-      if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
+      if (GET_CODE (PAT_VAR_LOCATION_LOC (rtl)) != PARALLEL)
        {
-         loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), mode,
-                                      initialized);
+         rtx loc = PAT_VAR_LOCATION_LOC (rtl);
+         if (GET_CODE (loc) == EXPR_LIST)
+           loc = XEXP (loc, 0);
+         loc_result = loc_descriptor (loc, mode, initialized);
          break;
        }
 
@@ -13804,10 +14124,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
          else
            {
              loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
-             loc_result->dw_loc_oprnd2.v.val_double.high
-               = CONST_DOUBLE_HIGH (rtl);
-             loc_result->dw_loc_oprnd2.v.val_double.low
-               = CONST_DOUBLE_LOW (rtl);
+             loc_result->dw_loc_oprnd2.v.val_double
+               = rtx_to_double_int (rtl);
            }
        }
       break;
@@ -13831,39 +14149,14 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
              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 ();
-                   }
+                 double_int val = rtx_to_double_int (elt);
 
                  if (elt_size <= sizeof (HOST_WIDE_INT))
-                   insert_int (lo, elt_size, p);
+                   insert_int (double_int_to_shwi (val), 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);
+                     insert_double (val, p);
                    }
                }
              break;
@@ -13986,9 +14279,11 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
     {
       gcc_assert (GET_CODE (varloc) == VAR_LOCATION);
       /* Single part.  */
-      if (GET_CODE (XEXP (varloc, 1)) != PARALLEL)
+      if (GET_CODE (PAT_VAR_LOCATION_LOC (varloc)) != PARALLEL)
        {
-         varloc = XEXP (XEXP (varloc, 1), 0);
+         varloc = PAT_VAR_LOCATION_LOC (varloc);
+         if (GET_CODE (varloc) == EXPR_LIST)
+           varloc = XEXP (varloc, 0);
          mode = GET_MODE (varloc);
          if (MEM_P (varloc))
            {
@@ -14011,7 +14306,11 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
     }
   else
     {
-      descr = loc_descriptor (varloc, DECL_MODE (loc), initialized);
+      if (GET_CODE (varloc) == VAR_LOCATION)
+       mode = DECL_MODE (PAT_VAR_LOCATION_DECL (varloc));
+      else
+       mode = DECL_MODE (loc);
+      descr = loc_descriptor (varloc, mode, initialized);
       have_address = 1;
     }
 
@@ -14061,6 +14360,125 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
   return descr;
 }
 
+/* Create a DW_OP_piece or DW_OP_bit_piece for bitsize, or return NULL
+   if it is not possible.  */
+
+static dw_loc_descr_ref
+new_loc_descr_op_bit_piece (HOST_WIDE_INT bitsize)
+{
+  if ((bitsize % BITS_PER_UNIT) == 0)
+    return new_loc_descr (DW_OP_piece, bitsize / BITS_PER_UNIT, 0);
+  else if (dwarf_version >= 3 || !dwarf_strict)
+    return new_loc_descr (DW_OP_bit_piece, bitsize, 0);
+  else
+    return NULL;
+}
+
+/* Helper function for dw_loc_list.  Compute proper Dwarf location descriptor
+   for VAR_LOC_NOTE for variable DECL that has been optimized by SRA.  */
+
+static dw_loc_descr_ref
+dw_sra_loc_expr (tree decl, rtx loc)
+{
+  rtx p;
+  unsigned int padsize = 0;
+  dw_loc_descr_ref descr, *descr_tail;
+  unsigned HOST_WIDE_INT decl_size;
+  rtx varloc;
+  enum var_init_status initialized;
+
+  if (DECL_SIZE (decl) == NULL
+      || !host_integerp (DECL_SIZE (decl), 1))
+    return NULL;
+
+  decl_size = tree_low_cst (DECL_SIZE (decl), 1);
+  descr = NULL;
+  descr_tail = &descr;
+
+  for (p = loc; p; p = XEXP (p, 1))
+    {
+      unsigned int bitsize = decl_piece_bitsize (p);
+      rtx loc_note = *decl_piece_varloc_ptr (p);
+      dw_loc_descr_ref cur_descr;
+      dw_loc_descr_ref *tail, last = NULL;
+      unsigned int opsize = 0;
+
+      if (loc_note == NULL_RTX
+         || NOTE_VAR_LOCATION_LOC (loc_note) == NULL_RTX)
+       {
+         padsize += bitsize;
+         continue;
+       }
+      initialized = NOTE_VAR_LOCATION_STATUS (loc_note);
+      varloc = NOTE_VAR_LOCATION (loc_note);
+      cur_descr = dw_loc_list_1 (decl, varloc, 2, initialized);
+      if (cur_descr == NULL)
+       {
+         padsize += bitsize;
+         continue;
+       }
+
+      /* Check that cur_descr either doesn't use
+        DW_OP_*piece operations, or their sum is equal
+        to bitsize.  Otherwise we can't embed it.  */
+      for (tail = &cur_descr; *tail != NULL;
+          tail = &(*tail)->dw_loc_next)
+       if ((*tail)->dw_loc_opc == DW_OP_piece)
+         {
+           opsize += (*tail)->dw_loc_oprnd1.v.val_unsigned
+                     * BITS_PER_UNIT;
+           last = *tail;
+         }
+       else if ((*tail)->dw_loc_opc == DW_OP_bit_piece)
+         {
+           opsize += (*tail)->dw_loc_oprnd1.v.val_unsigned;
+           last = *tail;
+         }
+
+      if (last != NULL && opsize != bitsize)
+       {
+         padsize += bitsize;
+         continue;
+       }
+
+      /* If there is a hole, add DW_OP_*piece after empty DWARF
+        expression, which means that those bits are optimized out.  */
+      if (padsize)
+       {
+         if (padsize > decl_size)
+           return NULL;
+         decl_size -= padsize;
+         *descr_tail = new_loc_descr_op_bit_piece (padsize);
+         if (*descr_tail == NULL)
+           return NULL;
+         descr_tail = &(*descr_tail)->dw_loc_next;
+         padsize = 0;
+       }
+      *descr_tail = cur_descr;
+      descr_tail = tail;
+      if (bitsize > decl_size)
+       return NULL;
+      decl_size -= bitsize;
+      if (last == NULL)
+       {
+         *descr_tail = new_loc_descr_op_bit_piece (bitsize);
+         if (*descr_tail == NULL)
+           return NULL;
+         descr_tail = &(*descr_tail)->dw_loc_next;
+       }
+    }
+
+  /* If there were any non-empty expressions, add padding till the end of
+     the decl.  */
+  if (descr != NULL && decl_size != 0)
+    {
+      *descr_tail = new_loc_descr_op_bit_piece (decl_size);
+      if (*descr_tail == NULL)
+       return NULL;
+    }
+  return descr;
+}
+
 /* Return the dwarf representation of the location list LOC_LIST of
    DECL.  WANT_ADDRESS has the same meaning as in loc_list_from_tree
    function.  */
@@ -14090,45 +14508,48 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
 
   secname = secname_for_decl (decl);
 
-  for (node = loc_list->first; node->next; node = node->next)
-    if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+  for (node = loc_list->first; node; node = node->next)
+    if (GET_CODE (node->loc) == EXPR_LIST
+       || NOTE_VAR_LOCATION_LOC (node->loc) != NULL_RTX)
       {
-       /* The variable has a location between NODE->LABEL and
-          NODE->NEXT->LABEL.  */
-       initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
-       varloc = NOTE_VAR_LOCATION (node->var_loc_note);
-       descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
+       if (GET_CODE (node->loc) == EXPR_LIST)
+         {
+           /* This requires DW_OP_{,bit_}piece, which is not usable
+              inside DWARF expressions.  */
+           if (want_address != 2)
+             continue;
+           descr = dw_sra_loc_expr (decl, node->loc);
+           if (descr == NULL)
+             continue;
+         }
+       else
+         {
+           initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
+           varloc = NOTE_VAR_LOCATION (node->loc);
+           descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
+         }
        if (descr)
          {
-           *listp = new_loc_list (descr, node->label, node->next->label,
-                                  secname);
+           /* The variable has a location between NODE->LABEL and
+              NODE->NEXT->LABEL.  */
+           if (node->next)
+             endname = node->next->label;
+           /* If the variable has a location at the last label
+              it keeps its location until the end of function.  */
+           else 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);
+             }
+
+           *listp = new_loc_list (descr, node->label, endname, secname);
            listp = &(*listp)->dw_loc_next;
          }
       }
 
-  /* 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)
-    {
-      initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
-      varloc = NOTE_VAR_LOCATION (node->var_loc_note);
-      descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
-      if (descr)
-       {
-         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);
-           }
-
-         *listp = new_loc_list (descr, node->label, endname, secname);
-         listp = &(*listp)->dw_loc_next;
-       }
-    }
-
   /* Try to avoid the overhead of a location list emitting a location
      expression instead, but only if we didn't have more than one
      location entry in the first place.  If some entries were not
@@ -15249,6 +15670,24 @@ extract_int (const unsigned char *src, unsigned int size)
   return val;
 }
 
+/* Writes double_int values to dw_vec_const array.  */
+
+static void
+insert_double (double_int val, unsigned char *dest)
+{
+  unsigned char *p0 = dest;
+  unsigned char *p1 = dest + sizeof (HOST_WIDE_INT);
+
+  if (WORDS_BIG_ENDIAN)
+    {
+      p0 = p1;
+      p1 = dest;
+    }
+
+  insert_int ((HOST_WIDE_INT) val.low, sizeof (HOST_WIDE_INT), p0);
+  insert_int ((HOST_WIDE_INT) val.high, sizeof (HOST_WIDE_INT), p1);
+}
+
 /* Writes floating point values to dw_vec_const array.  */
 
 static void
@@ -15328,39 +15767,14 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
            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 ();
-                 }
+               double_int val = rtx_to_double_int (elt);
 
                if (elt_size <= sizeof (HOST_WIDE_INT))
-                 insert_int (lo, elt_size, p);
+                 insert_int (double_int_to_shwi (val), 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);
+                   insert_double (val, p);
                  }
              }
            break;
@@ -15883,15 +16297,16 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
   loc_list = lookup_decl_loc (decl);
   if (loc_list
       && loc_list->first
-      && loc_list->first == loc_list->last
-      && NOTE_VAR_LOCATION (loc_list->first->var_loc_note)
-      && NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note))
+      && loc_list->first->next == NULL
+      && NOTE_P (loc_list->first->loc)
+      && NOTE_VAR_LOCATION (loc_list->first->loc)
+      && NOTE_VAR_LOCATION_LOC (loc_list->first->loc))
     {
       struct var_loc_node *node;
 
       node = loc_list->first;
-      rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
-      if (GET_CODE (rtl) != PARALLEL)
+      rtl = NOTE_VAR_LOCATION_LOC (node->loc);
+      if (GET_CODE (rtl) == EXPR_LIST)
        rtl = XEXP (rtl, 0);
       if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
          && add_const_value_attribute (die, rtl))
@@ -16290,14 +16705,49 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, remap_debug_filename (wd));
 }
 
+/* Return the default for DW_AT_lower_bound, or -1 if there is not any
+   default.  */
+
+static int
+lower_bound_default (void)
+{
+  switch (get_AT_unsigned (comp_unit_die, DW_AT_language))
+    {
+    case DW_LANG_C:
+    case DW_LANG_C89:
+    case DW_LANG_C99:
+    case DW_LANG_C_plus_plus:
+    case DW_LANG_ObjC:
+    case DW_LANG_ObjC_plus_plus:
+    case DW_LANG_Java:
+      return 0;
+    case DW_LANG_Fortran77:
+    case DW_LANG_Fortran90:
+    case DW_LANG_Fortran95:
+      return 1;
+    case DW_LANG_UPC:
+    case DW_LANG_D:
+    case DW_LANG_Python:
+      return dwarf_version >= 4 ? 0 : -1;
+    case DW_LANG_Ada95:
+    case DW_LANG_Ada83:
+    case DW_LANG_Cobol74:
+    case DW_LANG_Cobol85:
+    case DW_LANG_Pascal83:
+    case DW_LANG_Modula2:
+    case DW_LANG_PLI:
+      return dwarf_version >= 4 ? 1 : -1;
+    default:
+      return -1;
+    }
+}
+
 /* Given a tree node describing an array bound (either lower or upper) output
    a representation for that bound.  */
 
 static void
 add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
 {
-  int want_address = 2;
-
   switch (TREE_CODE (bound))
     {
     case ERROR_MARK:
@@ -16307,11 +16757,13 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
     case INTEGER_CST:
       {
        unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
+       int dflt;
 
        /* Use the default if possible.  */
        if (bound_attr == DW_AT_lower_bound
-           && (((is_c_family () || is_java ()) && integer_zerop (bound))
-               || (is_fortran () && integer_onep (bound))))
+           && host_integerp (bound, 0)
+           && (dflt = lower_bound_default ()) != -1
+           && tree_low_cst (bound, 0) == dflt)
          ;
 
        /* Otherwise represent the bound as an unsigned value with the
@@ -16358,7 +16810,6 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
            add_AT_die_ref (subrange_die, bound_attr, decl_die);
            break;
          }
-       want_address = 0;
       }
       /* FALLTHRU */
 
@@ -16370,15 +16821,23 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
        dw_die_ref ctx, decl_die;
        dw_loc_list_ref list;
 
-       list = loc_list_from_tree (bound, want_address);
-       if (list == NULL)
-         break;
-
-       if (single_element_loc_list_p (list))
+       list = loc_list_from_tree (bound, 2);
+       if (list == NULL || single_element_loc_list_p (list))
          {
-           add_AT_loc (subrange_die, bound_attr, list->expr);
-           break;
+           /* If DW_AT_*bound is not a reference nor constant, it is
+              a DWARF expression rather than location description.
+              For that loc_list_from_tree (bound, 0) is needed.
+              If that fails to give a single element list,
+              fall back to outputting this as a reference anyway.  */
+           dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
+           if (list2 && single_element_loc_list_p (list2))
+             {
+               add_AT_loc (subrange_die, bound_attr, list2->expr);
+               break;
+             }
          }
+       if (list == NULL)
+         break;
 
        if (current_function_decl == 0)
          ctx = comp_unit_die;
@@ -16679,8 +17138,7 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
       if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
          && TREE_PUBLIC (decl)
          && !DECL_ABSTRACT (decl)
-         && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
-         && !is_fortran ())
+         && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)))
        {
          /* Defer until we have an assembler name set.  */
          if (!DECL_ASSEMBLER_NAME_SET_P (decl))
@@ -16694,7 +17152,7 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
              deferred_asm_name = asm_name;
            }
          else if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-           add_AT_string (die, DW_AT_MIPS_linkage_name,
+           add_AT_string (die, AT_linkage_name,
                           IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
        }
     }
@@ -17212,11 +17670,11 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
       if (info->dimen[dim].lower_bound)
        {
          /* If it is the default value, omit it.  */
-         if ((is_c_family () || is_java ())
-             && integer_zerop (info->dimen[dim].lower_bound))
-           ;
-         else if (is_fortran ()
-                  && integer_onep (info->dimen[dim].lower_bound))
+         int dflt;
+
+         if (host_integerp (info->dimen[dim].lower_bound, 0)
+             && (dflt = lower_bound_default ()) != -1
+             && tree_low_cst (info->dimen[dim].lower_bound, 0) == dflt)
            ;
          else
            add_descr_info_field (subrange_die, DW_AT_lower_bound,
@@ -17319,6 +17777,9 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
                          scope_die_for (type, context_die), type);
       equate_type_number_to_die (type, type_die);
       add_name_attribute (type_die, type_tag (type));
+      if ((dwarf_version >= 4 || !dwarf_strict)
+         && ENUM_IS_SCOPED (type))
+       add_AT_flag (type_die, DW_AT_enum_class, 1);
     }
   else if (! TYPE_SIZE (type))
     return type_die;
@@ -18234,9 +18695,9 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 
   /* If the compiler emitted a definition for the DECL declaration
      and if we already emitted a DIE for it, don't emit a second
-     DIE for it again.  */
-  if (old_die
-      && declaration)
+     DIE for it again. Allow re-declarations of DECLs that are
+     inside functions, though.  */
+  if (old_die && declaration && !local_scope_p (context_die))
     return;
 
   /* For static data members, the declaration in the class is supposed
@@ -18564,8 +19025,12 @@ gen_pointer_type_die (tree type, dw_die_ref context_die)
 static void
 gen_reference_type_die (tree type, dw_die_ref context_die)
 {
-  dw_die_ref ref_die
-    = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type);
+  dw_die_ref ref_die, scope_die = scope_die_for (type, context_die);
+
+  if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
+    ref_die = new_die (DW_TAG_rvalue_reference_type, scope_die, type);
+  else
+    ref_die = new_die (DW_TAG_reference_type, scope_die, type);
 
   equate_type_number_to_die (type, ref_die);
   add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die);
@@ -18645,6 +19110,20 @@ gen_compile_unit_die (const char *filename)
     }
 
   add_AT_unsigned (die, DW_AT_language, language);
+
+  switch (language)
+    {
+    case DW_LANG_Fortran77:
+    case DW_LANG_Fortran90:
+    case DW_LANG_Fortran95:
+      /* Fortran has case insensitive identifiers and the front-end
+        lowercases everything.  */
+      add_AT_unsigned (die, DW_AT_identifier_case, DW_ID_down_case);
+      break;
+    default:
+      /* The default DW_ID_case_sensitive doesn't need to be specified.  */
+      break;
+    }
   return die;
 }
 
@@ -19065,7 +19544,19 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     case LANG_TYPE:
-      /* No Dwarf representation currently defined.  */
+      /* Just use DW_TAG_unspecified_type.  */
+      {
+        dw_die_ref type_die = lookup_type_die (type);
+        if (type_die == NULL)
+          {
+           tree name = TYPE_NAME (type);
+           if (TREE_CODE (name) == TYPE_DECL)
+             name = DECL_NAME (name);
+            type_die = new_die (DW_TAG_unspecified_type, comp_unit_die, type);
+            add_name_attribute (type_die, IDENTIFIER_POINTER (name));
+            equate_type_number_to_die (type, type_die);
+          }
+      }
       break;
 
     default:
@@ -19687,10 +20178,7 @@ dwarf2out_imported_module_or_decl_1 (tree decl,
 
   if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
     {
-      if (is_base_type (TREE_TYPE (decl)))
-       at_import_die = base_type_die (TREE_TYPE (decl));
-      else
-       at_import_die = force_type_die (TREE_TYPE (decl));
+      at_import_die = force_type_die (TREE_TYPE (decl));
       /* For namespace N { typedef void T; } using N::T; base_type_die
         returns NULL, but DW_TAG_imported_declaration requires
         the DW_AT_import tag.  Force creation of DW_TAG_typedef.  */
@@ -19921,6 +20409,16 @@ dwarf2out_decl (tree decl)
   gen_decl_die (decl, NULL, context_die);
 }
 
+/* Write the debugging output for DECL.  */
+
+static void
+dwarf2out_function_decl (tree decl)
+{
+  dwarf2out_decl (decl);
+
+  htab_empty (decl_loc_table);
+}
+
 /* Output a marker (i.e. a label) for the beginning of the generated code for
    a lexical block.  */
 
@@ -20281,25 +20779,34 @@ dwarf2out_var_location (rtx loc_note)
   if (next_real == NULL_RTX)
     return;
 
+  /* If there were any real insns between note we processed last time
+     and this note (or if it is the first note), clear
+     last_{,postcall_}label so that they are not reused this time.  */
+  if (last_var_location_insn == NULL_RTX
+      || last_var_location_insn != next_real
+      || last_in_cold_section_p != in_cold_section_p)
+    {
+      last_label = NULL;
+      last_postcall_label = NULL;
+    }
+
   decl = NOTE_VAR_LOCATION_DECL (loc_note);
-  newloc = add_var_loc_to_decl (decl, loc_note);
+  newloc = add_var_loc_to_decl (decl, loc_note,
+                               NOTE_DURING_CALL_P (loc_note)
+                               ? last_postcall_label : last_label);
   if (newloc == NULL)
     return;
 
   /* If there were no real insns between note we processed last time
-     and this note, use the label we emitted last time.  */
-  if (last_var_location_insn == NULL_RTX
-      || last_var_location_insn != next_real
-      || last_in_cold_section_p != in_cold_section_p)
+     and this note, use the label we emitted last time.  Otherwise
+     create a new label and emit it.  */
+  if (last_label == NULL)
     {
       ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
       ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
       loclabel_num++;
       last_label = ggc_strdup (loclabel);
-      last_postcall_label = NULL;
     }
-  newloc->var_loc_note = loc_note;
-  newloc->next = NULL;
 
   if (!NOTE_DURING_CALL_P (loc_note))
     newloc->label = last_label;
@@ -20313,11 +20820,6 @@ dwarf2out_var_location (rtx loc_note)
       newloc->label = last_postcall_label;
     }
 
-  if (cfun && in_cold_section_p)
-    newloc->section_label = crtl->subsections.cold_section_label;
-  else
-    newloc->section_label = text_section_label;
-
   last_var_location_insn = next_real;
   last_in_cold_section_p = in_cold_section_p;
 }
@@ -20330,8 +20832,6 @@ dwarf2out_var_location (rtx loc_note)
 static void
 dwarf2out_begin_function (tree fun)
 {
-  htab_empty (decl_loc_table);
-
   if (function_section (fun) != text_section)
     have_multiple_function_sections = true;
 
@@ -20834,6 +21334,7 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_packed_type:
     case DW_TAG_pointer_type:
     case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
     case DW_TAG_volatile_type:
     case DW_TAG_typedef:
     case DW_TAG_array_type:
@@ -21053,7 +21554,7 @@ htab_ct_eq (const void *of1, const void *of2)
                     DWARF_TYPE_SIGNATURE_SIZE));
 }
 
-/* Move a DW_AT_MIPS_linkage_name attribute just added to dw_die_ref
+/* Move a DW_AT_{,MIPS_}linkage_name attribute just added to dw_die_ref
    to the location it would have been added, should we know its
    DECL_ASSEMBLER_NAME when we added other attributes.  This will
    probably improve compactness of debug info, removing equivalent
@@ -21066,7 +21567,7 @@ move_linkage_attr (dw_die_ref die)
   unsigned ix = VEC_length (dw_attr_node, die->die_attr);
   dw_attr_node linkage = *VEC_index (dw_attr_node, die->die_attr, ix - 1);
 
-  gcc_assert (linkage.dw_attr == DW_AT_MIPS_linkage_name);
+  gcc_assert (linkage.dw_attr == AT_linkage_name);
 
   while (--ix > 0)
     {
@@ -21110,7 +21611,6 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED)
 
   if (GET_CODE (rtl) == SYMBOL_REF
       && SYMBOL_REF_DECL (rtl)
-      && TREE_CODE (SYMBOL_REF_DECL (rtl)) == VAR_DECL
       && !TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl)))
     return 1;
 
@@ -21300,7 +21800,7 @@ dwarf2out_finish (const char *filename)
       tree decl = node->created_for;
       if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
        {
-         add_AT_string (node->die, DW_AT_MIPS_linkage_name,
+         add_AT_string (node->die, AT_linkage_name,
                         IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
          move_linkage_attr (node->die);
        }