OSDN Git Service

* dwarf2out.c (dwarf2out_switch_text_section): Do not call
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 140baf1..829b9ee 100644 (file)
@@ -1,6 +1,6 @@
 /* Output Dwarf2 format symbol table information from GCC.
    Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
@@ -9,7 +9,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -18,9 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* TODO: Emit .debug_line header even when there are no functions, since
           the file numbers are used by .debug_info.  Alternately, leave
@@ -34,6 +33,29 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
    information.  */
 
+/* DWARF2 Abbreviation Glossary:
+
+   CFA = Canonical Frame Address
+          a fixed address on the stack which identifies a call frame.
+          We define it to be the value of SP just before the call insn.
+          The CFA register and offset, which may change during the course
+          of the function, are used to calculate its value at runtime.
+
+   CFI = Call Frame Instruction
+          an instruction for the DWARF2 abstract machine
+
+   CIE = Common Information Entry
+          information describing information common to one or more FDEs
+
+   DIE = Debugging Information Entry
+
+   FDE = Frame Description Entry
+          information describing the stack call frame, in particular,
+          how to restore registers
+
+   DW_CFA_... = DWARF2 CFA call frame instruction
+   DW_TAG_... = DWARF2 DIE tag */
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -72,24 +94,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 static void dwarf2out_source_line (unsigned int, const char *);
 #endif
 
-/* DWARF2 Abbreviation Glossary:
-   CFA = Canonical Frame Address
-          a fixed address on the stack which identifies a call frame.
-          We define it to be the value of SP just before the call insn.
-          The CFA register and offset, which may change during the course
-          of the function, are used to calculate its value at runtime.
-   CFI = Call Frame Instruction
-          an instruction for the DWARF2 abstract machine
-   CIE = Common Information Entry
-          information describing information common to one or more FDEs
-   DIE = Debugging Information Entry
-   FDE = Frame Description Entry
-          information describing the stack call frame, in particular,
-          how to restore registers
-
-   DW_CFA_... = DWARF2 CFA call frame instruction
-   DW_TAG_... = DWARF2 DIE tag */
-
 #ifndef DWARF2_FRAME_INFO
 # ifdef DWARF2_DEBUGGING_INFO
 #  define DWARF2_FRAME_INFO \
@@ -335,6 +339,17 @@ static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
 static GTY(()) int dw2_string_counter;
 static GTY(()) unsigned long dwarf2out_cfi_label_num;
 
+/* True if the compilation unit places functions in more than one section.  */
+static GTY(()) bool have_multiple_function_sections = false;
+
+/* Whether the default text and cold text sections have been used at all.  */
+
+static GTY(()) bool text_section_used = false;
+static GTY(()) bool cold_text_section_used = false;
+
+/* The default cold text section.  */
+static GTY(()) section *cold_text_section;
+
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
 /* Forward declarations for functions defined in this file.  */
@@ -350,12 +365,13 @@ static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT);
 #ifdef DWARF2_UNWIND_INFO
 static void initial_return_save (rtx);
 #endif
-static HOST_WIDE_INT stack_adjust_offset (rtx);
+static HOST_WIDE_INT stack_adjust_offset (const_rtx);
 static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
 static void output_call_frame_info (int);
+static void dwarf2out_note_section_used (void);
 static void dwarf2out_stack_adjust (rtx, bool);
 static void flush_queued_reg_saves (void);
-static bool clobbers_queued_reg_save (rtx);
+static bool clobbers_queued_reg_save (const_rtx);
 static void dwarf2out_frame_debug_expr (rtx, const char *);
 
 /* Support for complex CFA locations.  */
@@ -1021,10 +1037,10 @@ initial_return_save (rtx rtl)
    contains.  */
 
 static HOST_WIDE_INT
-stack_adjust_offset (rtx pattern)
+stack_adjust_offset (const_rtx pattern)
 {
-  rtx src = SET_SRC (pattern);
-  rtx dest = SET_DEST (pattern);
+  const_rtx src = SET_SRC (pattern);
+  const_rtx dest = SET_DEST (pattern);
   HOST_WIDE_INT offset = 0;
   enum rtx_code code;
 
@@ -1282,7 +1298,7 @@ flush_queued_reg_saves (void)
    have a new location for?  */
 
 static bool
-clobbers_queued_reg_save (rtx insn)
+clobbers_queued_reg_save (const_rtx insn)
 {
   struct queued_reg_save *q;
 
@@ -2219,6 +2235,7 @@ output_call_frame_info (int for_eh)
      specialization doesn't.  */
   if (TARGET_USES_WEAK_UNWIND_INFO
       && ! flag_asynchronous_unwind_tables
+      && flag_exceptions
       && for_eh)
     for (i = 0; i < fde_table_in_use; i++)
       if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
@@ -2419,12 +2436,6 @@ output_call_frame_info (int for_eh)
 
       if (for_eh)
        {
-         rtx sym_ref = gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin);
-         SYMBOL_REF_FLAGS (sym_ref) |= SYMBOL_FLAG_LOCAL;
-         dw2_asm_output_encoded_addr_rtx (fde_encoding,
-                                          sym_ref,
-                                          false,
-                                          "FDE initial location");
          if (fde->dw_fde_switched_sections)
            {
              rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode,
@@ -2447,14 +2458,20 @@ output_call_frame_info (int for_eh)
                                    "FDE address range");
            }
          else
-           dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
-                                 fde->dw_fde_end, fde->dw_fde_begin,
-                                 "FDE address range");
+           {
+             rtx sym_ref = gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin);
+             SYMBOL_REF_FLAGS (sym_ref) |= SYMBOL_FLAG_LOCAL;
+             dw2_asm_output_encoded_addr_rtx (fde_encoding,
+                                              sym_ref,
+                                              false,
+                                              "FDE initial location");
+             dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
+                                   fde->dw_fde_end, fde->dw_fde_begin,
+                                   "FDE address range");
+           }
        }
       else
        {
-         dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
-                              "FDE initial location");
          if (fde->dw_fde_switched_sections)
            {
              dw2_asm_output_addr (DWARF2_ADDR_SIZE,
@@ -2473,9 +2490,13 @@ output_call_frame_info (int for_eh)
                                    "FDE address range");
            }
          else
-           dw2_asm_output_delta (DWARF2_ADDR_SIZE,
-                                 fde->dw_fde_end, fde->dw_fde_begin,
-                                 "FDE address range");
+           {
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
+                                  "FDE initial location");
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                                   fde->dw_fde_end, fde->dw_fde_begin,
+                                   "FDE address range");
+           }
        }
 
       if (augmentation[0])
@@ -2658,7 +2679,7 @@ dwarf2out_frame_init (void)
   dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
 
 #ifdef DWARF2_UNWIND_INFO
-  if (DWARF2_UNWIND_INFO)
+  if (DWARF2_UNWIND_INFO || DWARF2_FRAME_INFO)
     initial_return_save (INCOMING_RETURN_ADDR_RTX);
 #endif
 }
@@ -2676,6 +2697,42 @@ dwarf2out_frame_finish (void)
     output_call_frame_info (1);
 #endif
 }
+
+/* Note that the current function section is being used for code.  */
+
+static void
+dwarf2out_note_section_used (void)
+{
+  section *sec = current_function_section ();
+  if (sec == text_section)
+    text_section_used = true;
+  else if (sec == cold_text_section)
+    cold_text_section_used = true;
+}
+
+void
+dwarf2out_switch_text_section (void)
+{
+  dw_fde_ref fde;
+
+  gcc_assert (cfun);
+
+  fde = &fde_table[fde_table_in_use - 1];
+  fde->dw_fde_switched_sections = true;
+  fde->dw_fde_hot_section_label = cfun->hot_section_label;
+  fde->dw_fde_hot_section_end_label = cfun->hot_section_end_label;
+  fde->dw_fde_unlikely_section_label = cfun->cold_section_label;
+  fde->dw_fde_unlikely_section_end_label = cfun->cold_section_end_label;
+  have_multiple_function_sections = true;
+
+  /* Reset the current label on switching text sections, so that we
+     don't attempt to advance_loc4 between labels in different sections.  */
+  fde->dw_fde_current_label = NULL;
+
+  /* There is no need to mark used sections when not debugging.  */
+  if (cold_text_section != NULL)
+    dwarf2out_note_section_used ();
+}
 #endif
 \f
 /* And now, the subset of the debugging information support code necessary
@@ -2695,6 +2752,7 @@ struct dwarf_file_data GTY(())
 
 typedef struct dw_val_struct *dw_val_ref;
 typedef struct die_struct *dw_die_ref;
+typedef const struct die_struct *const_dw_die_ref;
 typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
 typedef struct dw_loc_list_struct *dw_loc_list_ref;
 
@@ -3120,6 +3178,8 @@ dwarf_stack_op_name (unsigned int op)
       return "DW_OP_call_ref";
     case DW_OP_GNU_push_tls_address:
       return "DW_OP_GNU_push_tls_address";
+    case DW_OP_GNU_uninit:
+      return "DW_OP_GNU_uninit";
     default:
       return "OP_<unknown>";
     }
@@ -3644,14 +3704,13 @@ static void dwarf2out_start_source_file (unsigned, const char *);
 static void dwarf2out_end_source_file (unsigned);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
-static bool dwarf2out_ignore_block (tree);
+static bool dwarf2out_ignore_block (const_tree);
 static void dwarf2out_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree);
 static void dwarf2out_abstract_function (tree);
 static void dwarf2out_var_location (rtx);
 static void dwarf2out_begin_function (tree);
-static void dwarf2out_switch_text_section (void);
 
 /* The debug hooks structure.  */
 
@@ -3710,6 +3769,7 @@ typedef struct dw_line_info_struct *dw_line_info_ref;
 typedef struct dw_separate_line_info_struct *dw_separate_line_info_ref;
 typedef struct pubname_struct *pubname_ref;
 typedef struct dw_ranges_struct *dw_ranges_ref;
+typedef struct dw_ranges_by_label_struct *dw_ranges_by_label_ref;
 
 /* Each entry in the line_info_table maintains the file and
    line number associated with the label generated for that
@@ -3792,7 +3852,15 @@ DEF_VEC_ALLOC_O(pubname_entry, gc);
 
 struct dw_ranges_struct GTY(())
 {
-  int block_num;
+  /* If this is positive, it's a block number, otherwise it's a
+     bitwise-negated index into dw_ranges_by_label.  */
+  int num;
+};
+
+struct dw_ranges_by_label_struct GTY(())
+{
+  const char *begin;
+  const char *end;
 };
 
 /* The limbo die list structure.  */
@@ -3951,9 +4019,6 @@ static GTY(()) unsigned line_info_table_allocated;
 /* Number of elements in line_info_table currently in use.  */
 static GTY(()) unsigned line_info_table_in_use;
 
-/* True if the compilation unit places functions in more than one section.  */
-static GTY(()) bool have_multiple_function_sections = false;
-
 /* A pointer to the base of a table that contains line information
    for each source code line outside of .text in the compilation unit.  */
 static GTY ((length ("separate_line_info_table_allocated")))
@@ -3999,6 +4064,16 @@ static GTY(()) unsigned ranges_table_allocated;
 /* Number of elements in ranges_table currently in use.  */
 static GTY(()) unsigned ranges_table_in_use;
 
+/* Array of pairs of labels referenced in ranges_table.  */
+static GTY ((length ("ranges_by_label_allocated")))
+     dw_ranges_by_label_ref ranges_by_label;
+
+/* Number of elements currently allocated for ranges_by_label.  */
+static GTY(()) unsigned ranges_by_label_allocated;
+
+/* Number of elements in ranges_by_label currently in use.  */
+static GTY(()) unsigned ranges_by_label_in_use;
+
 /* Size (in elements) of increments by which we may expand the
    ranges_table.  */
 #define RANGES_TABLE_INCREMENT 64
@@ -4034,14 +4109,14 @@ static HOST_WIDE_INT frame_pointer_fb_offset;
 
 /* Forward declarations for functions defined in this file.  */
 
-static int is_pseudo_reg (rtx);
+static int is_pseudo_reg (const_rtx);
 static tree type_main_variant (tree);
-static int is_tagged_type (tree);
+static int is_tagged_type (const_tree);
 static const char *dwarf_tag_name (unsigned);
 static const char *dwarf_attr_name (unsigned);
 static const char *dwarf_form_name (unsigned);
-static tree decl_ultimate_origin (tree);
-static tree block_ultimate_origin (tree);
+static tree decl_ultimate_origin (const_tree);
+static tree block_ultimate_origin (const_tree);
 static tree decl_class_context (tree);
 static void add_dwarf_attr (dw_die_ref, dw_attr_ref);
 static inline enum dw_val_class AT_class (dw_attr_ref);
@@ -4104,7 +4179,7 @@ static int decl_die_table_eq (const void *, const void *);
 static dw_die_ref lookup_decl_die (tree);
 static hashval_t decl_loc_table_hash (const void *);
 static int decl_loc_table_eq (const void *, const void *);
-static var_loc_list *lookup_decl_loc (tree);
+static var_loc_list *lookup_decl_loc (const_tree);
 static void equate_decl_number_to_die (tree, dw_die_ref);
 static void add_var_loc_to_decl (tree, struct var_loc_node *);
 static void print_spaces (FILE *);
@@ -4116,7 +4191,7 @@ static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *);
 static void attr_checksum (dw_attr_ref, struct md5_ctx *, int *);
 static void die_checksum (dw_die_ref, struct md5_ctx *, int *);
 static int same_loc_p (dw_loc_descr_ref, dw_loc_descr_ref, int *);
-static int same_dw_val_p (dw_val_node *, dw_val_node *, int *);
+static int same_dw_val_p (const dw_val_node *, const dw_val_node *, int *);
 static int same_attr_p (dw_attr_ref, dw_attr_ref, int *);
 static int same_die_p (dw_die_ref, dw_die_ref, int *);
 static int same_die_p_wrap (dw_die_ref, dw_die_ref);
@@ -4155,42 +4230,49 @@ static void add_pubtype (tree, dw_die_ref);
 static void output_pubnames (VEC (pubname_entry,gc) *);
 static void add_arange (tree, dw_die_ref);
 static void output_aranges (void);
-static unsigned int add_ranges (tree);
+static unsigned int add_ranges_num (int);
+static unsigned int add_ranges (const_tree);
+static unsigned int add_ranges_by_labels (const char *, const char *);
 static void output_ranges (void);
 static void output_line_info (void);
 static void output_file_names (void);
 static dw_die_ref base_type_die (tree);
 static int is_base_type (tree);
-static bool is_subrange_type (tree);
+static bool is_subrange_type (const_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 dbx_reg_number (rtx);
+static int type_is_enum (const_tree);
+static unsigned int dbx_reg_number (const_rtx);
 static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
-static dw_loc_descr_ref reg_loc_descriptor (rtx);
-static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
-static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
+static dw_loc_descr_ref reg_loc_descriptor (rtx, enum var_init_status);
+static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int, 
+                                               enum var_init_status);
+static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx,
+                                                    enum var_init_status);
 static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
-static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT);
-static int is_based_loc (rtx);
-static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode);
-static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
-static dw_loc_descr_ref loc_descriptor (rtx);
+static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT,
+                                        enum var_init_status);
+static int is_based_loc (const_rtx);
+static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode,
+                                           enum var_init_status);
+static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
+                                              enum var_init_status);
+static dw_loc_descr_ref loc_descriptor (rtx, enum var_init_status);
 static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
 static dw_loc_descr_ref loc_descriptor_from_tree (tree);
 static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
-static tree field_type (tree);
-static unsigned int simple_type_align_in_bits (tree);
-static unsigned int simple_decl_align_in_bits (tree);
-static unsigned HOST_WIDE_INT simple_type_size_in_bits (tree);
-static HOST_WIDE_INT field_byte_offset (tree);
+static tree field_type (const_tree);
+static unsigned int simple_type_align_in_bits (const_tree);
+static unsigned int simple_decl_align_in_bits (const_tree);
+static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
+static HOST_WIDE_INT field_byte_offset (const_tree);
 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 void insert_float (const_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);
@@ -4214,12 +4296,13 @@ static inline int local_scope_p (dw_die_ref);
 static inline int class_or_namespace_scope_p (dw_die_ref);
 static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
 static void add_calling_convention_attribute (dw_die_ref, tree);
-static const char *type_tag (tree);
-static tree member_declared_type (tree);
+static const char *type_tag (const_tree);
+static tree member_declared_type (const_tree);
 #if 0
 static const char *decl_start_label (tree);
 #endif
 static void gen_array_type_die (tree, dw_die_ref);
+static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_ref);
 #if 0
 static void gen_entry_point_die (tree, dw_die_ref);
 #endif
@@ -4248,7 +4331,7 @@ static void gen_type_die (tree, dw_die_ref);
 static void gen_tagged_type_instantiation_die (tree, dw_die_ref);
 static void gen_block_die (tree, dw_die_ref, int);
 static void decls_for_scope (tree, dw_die_ref, int);
-static int is_redundant_typedef (tree);
+static int is_redundant_typedef (const_tree);
 static void gen_namespace_die (tree);
 static void gen_decl_die (tree, dw_die_ref);
 static dw_die_ref force_decl_die (tree);
@@ -4312,7 +4395,7 @@ static int maybe_emit_file (struct dwarf_file_data *fd);
 
 /* Section flags for .debug_str section.  */
 #define DEBUG_STR_SECTION_FLAGS \
-  (HAVE_GAS_SHF_MERGE && flag_merge_constants                  \
+  (HAVE_GAS_SHF_MERGE && flag_merge_debug_strings              \
    ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1       \
    : SECTION_DEBUG)
 
@@ -4379,6 +4462,7 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 #ifndef SEPARATE_LINE_CODE_LABEL
 #define SEPARATE_LINE_CODE_LABEL       "LSM"
 #endif
+
 \f
 /* We allow a language front-end to designate a function that is to be
    called to "demangle" any name before it is put into a DIE.  */
@@ -4394,7 +4478,7 @@ dwarf2out_set_demangle_name_func (const char *(*func) (const char *))
 /* Test if rtl node points to a pseudo register.  */
 
 static inline int
-is_pseudo_reg (rtx rtl)
+is_pseudo_reg (const_rtx rtl)
 {
   return ((REG_P (rtl) && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
          || (GET_CODE (rtl) == SUBREG
@@ -4424,7 +4508,7 @@ type_main_variant (tree type)
 /* Return nonzero if the given type node represents a tagged type.  */
 
 static inline int
-is_tagged_type (tree type)
+is_tagged_type (const_tree type)
 {
   enum tree_code code = TREE_CODE (type);
 
@@ -4517,8 +4601,6 @@ dwarf_tag_name (unsigned int tag)
       return "DW_TAG_namelist";
     case DW_TAG_namelist_item:
       return "DW_TAG_namelist_item";
-    case DW_TAG_namespace:
-      return "DW_TAG_namespace";
     case DW_TAG_packed_type:
       return "DW_TAG_packed_type";
     case DW_TAG_subprogram:
@@ -4537,8 +4619,26 @@ dwarf_tag_name (unsigned int tag)
       return "DW_TAG_variable";
     case DW_TAG_volatile_type:
       return "DW_TAG_volatile_type";
+    case DW_TAG_dwarf_procedure:
+      return "DW_TAG_dwarf_procedure";
+    case DW_TAG_restrict_type:
+      return "DW_TAG_restrict_type";
+    case DW_TAG_interface_type:
+      return "DW_TAG_interface_type";
+    case DW_TAG_namespace:
+      return "DW_TAG_namespace";
     case DW_TAG_imported_module:
       return "DW_TAG_imported_module";
+    case DW_TAG_unspecified_type:
+      return "DW_TAG_unspecified_type";
+    case DW_TAG_partial_unit:
+      return "DW_TAG_partial_unit";
+    case DW_TAG_imported_unit:
+      return "DW_TAG_imported_unit";
+    case DW_TAG_condition:
+      return "DW_TAG_condition";
+    case DW_TAG_shared_type:
+      return "DW_TAG_shared_type";
     case DW_TAG_MIPS_loop:
       return "DW_TAG_MIPS_loop";
     case DW_TAG_format_label:
@@ -4625,8 +4725,8 @@ dwarf_attr_name (unsigned int attr)
       return "DW_AT_return_addr";
     case DW_AT_start_scope:
       return "DW_AT_start_scope";
-    case DW_AT_stride_size:
-      return "DW_AT_stride_size";
+    case DW_AT_bit_stride:
+      return "DW_AT_bit_stride";
     case DW_AT_upper_bound:
       return "DW_AT_upper_bound";
     case DW_AT_abstract_origin:
@@ -4694,8 +4794,8 @@ dwarf_attr_name (unsigned int attr)
       return "DW_AT_associated";
     case DW_AT_data_location:
       return "DW_AT_data_location";
-    case DW_AT_stride:
-      return "DW_AT_stride";
+    case DW_AT_byte_stride:
+      return "DW_AT_byte_stride";
     case DW_AT_entry_pc:
       return "DW_AT_entry_pc";
     case DW_AT_use_UTF8:
@@ -4820,7 +4920,7 @@ dwarf_form_name (unsigned int form)
    given block.  */
 
 static tree
-decl_ultimate_origin (tree decl)
+decl_ultimate_origin (const_tree decl)
 {
   if (!CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_COMMON))
     return NULL_TREE;
@@ -4845,7 +4945,7 @@ decl_ultimate_origin (tree decl)
    given block.  */
 
 static tree
-block_ultimate_origin (tree block)
+block_ultimate_origin (const_tree block)
 {
   tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
 
@@ -5652,7 +5752,7 @@ equate_type_number_to_die (tree type, dw_die_ref type_die)
 static hashval_t
 decl_die_table_hash (const void *x)
 {
-  return (hashval_t) ((const dw_die_ref) x)->decl_id;
+  return (hashval_t) ((const_dw_die_ref) x)->decl_id;
 }
 
 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
@@ -5660,7 +5760,7 @@ decl_die_table_hash (const void *x)
 static int
 decl_die_table_eq (const void *x, const void *y)
 {
-  return (((const dw_die_ref) x)->decl_id == DECL_UID ((const tree) y));
+  return (((const_dw_die_ref) x)->decl_id == DECL_UID ((const_tree) y));
 }
 
 /* Return the DIE associated with a given declaration.  */
@@ -5685,13 +5785,13 @@ decl_loc_table_hash (const void *x)
 static int
 decl_loc_table_eq (const void *x, const void *y)
 {
-  return (((const var_loc_list *) x)->decl_id == DECL_UID ((const tree) y));
+  return (((const var_loc_list *) x)->decl_id == DECL_UID ((const_tree) y));
 }
 
 /* Return the var_loc list associated with a given declaration.  */
 
 static inline var_loc_list *
-lookup_decl_loc (tree decl)
+lookup_decl_loc (const_tree decl)
 {
   return htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
 }
@@ -5731,9 +5831,16 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
   if (temp->last)
     {
       /* 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->var_loc_note)))
+      if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
+                        NOTE_VAR_LOCATION_LOC (loc->var_loc_note)))
+         || ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
+              != NOTE_VAR_LOCATION_STATUS (loc->var_loc_note))
+             && ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
+                  == VAR_INIT_STATUS_UNINITIALIZED)
+                 || (NOTE_VAR_LOCATION_STATUS (loc->var_loc_note)
+                     == VAR_INIT_STATUS_UNINITIALIZED))))
        {
          /* Add LOC to the end of list and update LAST.  */
          temp->last->next = loc;
@@ -6049,7 +6156,7 @@ same_loc_p (dw_loc_descr_ref loc1, dw_loc_descr_ref loc2, int *mark)
 
 /* Do the values look the same?  */
 static int
-same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark)
+same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
 {
   dw_loc_descr_ref loc1, loc2;
   rtx r1, r2;
@@ -6249,6 +6356,7 @@ is_type_die (dw_die_ref die)
     {
     case DW_TAG_array_type:
     case DW_TAG_class_type:
+    case DW_TAG_interface_type:
     case DW_TAG_enumeration_type:
     case DW_TAG_pointer_type:
     case DW_TAG_reference_type:
@@ -6812,7 +6920,10 @@ size_of_aranges (void)
   size = DWARF_ARANGES_HEADER_SIZE;
 
   /* Count the address/length pair for this compilation unit.  */
-  size += 2 * DWARF2_ADDR_SIZE;
+  if (text_section_used)
+    size += 2 * DWARF2_ADDR_SIZE;
+  if (cold_text_section_used)
+    size += 2 * DWARF2_ADDR_SIZE;
   size += 2 * DWARF2_ADDR_SIZE * arange_table_in_use;
 
   /* Count the two zero words used to terminated the address range table.  */
@@ -7010,26 +7121,6 @@ add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr,
   *d = new_loc_list (descr, begin, end, section, 0);
 }
 
-static void
-dwarf2out_switch_text_section (void)
-{
-  dw_fde_ref fde;
-
-  gcc_assert (cfun);
-
-  fde = &fde_table[fde_table_in_use - 1];
-  fde->dw_fde_switched_sections = true;
-  fde->dw_fde_hot_section_label = cfun->hot_section_label;
-  fde->dw_fde_hot_section_end_label = cfun->hot_section_end_label;
-  fde->dw_fde_unlikely_section_label = cfun->cold_section_label;
-  fde->dw_fde_unlikely_section_end_label = cfun->cold_section_end_label;
-  have_multiple_function_sections = true;
-
-  /* Reset the current label on switching text sections, so that we
-     don't attempt to advance_loc4 between labels in different sections.  */
-  fde->dw_fde_current_label = NULL;
-}
-
 /* Output the location list given to us.  */
 
 static void
@@ -7043,6 +7134,9 @@ output_loc_list (dw_loc_list_ref list_head)
   for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
     {
       unsigned long size;
+      /* Don't output an entry that starts and ends at the same address.  */
+      if (strcmp (curr->begin, curr->end) == 0)
+       continue;
       if (!have_multiple_function_sections)
        {
          dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
@@ -7510,10 +7604,18 @@ output_aranges (void)
        dw2_asm_output_data (2, 0, NULL);
     }
 
-  dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address");
-  dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label,
-                       text_section_label, "Length");
-  if (flag_reorder_blocks_and_partition)
+  /* It is necessary not to output these entries if the sections were
+     not used; if the sections were not used, the length will be 0 and
+     the address may end up as 0 if the section is discarded by ld
+     --gc-sections, leaving an invalid (0, 0) entry that can be
+     confused with the terminator.  */
+  if (text_section_used)
+    {
+      dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address");
+      dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label,
+                           text_section_label, "Length");
+    }
+  if (cold_text_section_used)
     {
       dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label,
                           "Address");
@@ -7565,7 +7667,7 @@ output_aranges (void)
    was placed.  */
 
 static unsigned int
-add_ranges (tree block)
+add_ranges_num (int num)
 {
   unsigned int in_use = ranges_table_in_use;
 
@@ -7579,12 +7681,48 @@ add_ranges (tree block)
              RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
     }
 
-  ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0);
+  ranges_table[in_use].num = num;
   ranges_table_in_use = in_use + 1;
 
   return in_use * 2 * DWARF2_ADDR_SIZE;
 }
 
+/* Add a new entry to .debug_ranges corresponding to a block, or a
+   range terminator if BLOCK is NULL.  */
+
+static unsigned int
+add_ranges (const_tree block)
+{
+  return add_ranges_num (block ? BLOCK_NUMBER (block) : 0);
+}
+
+/* Add a new entry to .debug_ranges corresponding to a pair of
+   labels.  */
+
+static unsigned int
+add_ranges_by_labels (const char *begin, const char *end)
+{
+  unsigned int in_use = ranges_by_label_in_use;
+
+  if (in_use == ranges_by_label_allocated)
+    {
+      ranges_by_label_allocated += RANGES_TABLE_INCREMENT;
+      ranges_by_label
+       = ggc_realloc (ranges_by_label,
+                      (ranges_by_label_allocated
+                       * sizeof (struct dw_ranges_by_label_struct)));
+      memset (ranges_by_label + ranges_by_label_in_use, 0,
+             RANGES_TABLE_INCREMENT
+             * sizeof (struct dw_ranges_by_label_struct));
+    }
+
+  ranges_by_label[in_use].begin = begin;
+  ranges_by_label[in_use].end = end;
+  ranges_by_label_in_use = in_use + 1;
+
+  return add_ranges_num (-(int)in_use - 1);
+}
+
 static void
 output_ranges (void)
 {
@@ -7594,9 +7732,9 @@ output_ranges (void)
 
   for (i = 0; i < ranges_table_in_use; i++)
     {
-      int block_num = ranges_table[i].block_num;
+      int block_num = ranges_table[i].num;
 
-      if (block_num)
+      if (block_num > 0)
        {
          char blabel[MAX_ARTIFICIAL_LABEL_BYTES];
          char elabel[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -7616,10 +7754,10 @@ output_ranges (void)
                                    text_section_label, NULL);
            }
 
-         /* Otherwise, we add a DW_AT_entry_pc attribute to force the
-            compilation unit base address to zero, which allows us to
-            use absolute addresses, and not worry about whether the
-            target supports cross-section arithmetic.  */
+         /* Otherwise, the compilation unit base address is zero,
+            which allows us to use absolute addresses, and not worry
+            about whether the target supports cross-section
+            arithmetic.  */
          else
            {
              dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
@@ -7629,6 +7767,38 @@ output_ranges (void)
 
          fmt = NULL;
        }
+
+      /* Negative block_num stands for an index into ranges_by_label.  */
+      else if (block_num < 0)
+       {
+         int lab_idx = - block_num - 1;
+
+         if (!have_multiple_function_sections)
+           {
+             gcc_unreachable ();
+#if 0
+             /* If we ever use add_ranges_by_labels () for a single
+                function section, all we have to do is to take out
+                the #if 0 above.  */
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                                   ranges_by_label[lab_idx].begin,
+                                   text_section_label,
+                                   fmt, i * 2 * DWARF2_ADDR_SIZE);
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                                   ranges_by_label[lab_idx].end,
+                                   text_section_label, NULL);
+#endif
+           }
+         else
+           {
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE,
+                                  ranges_by_label[lab_idx].begin,
+                                  fmt, i * 2 * DWARF2_ADDR_SIZE);
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE,
+                                  ranges_by_label[lab_idx].end,
+                                  NULL);
+           }
+       }
       else
        {
          dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
@@ -7667,8 +7837,8 @@ file_info_cmp (const void *p1, const void *p2)
 {
   const struct file_info *s1 = p1;
   const struct file_info *s2 = p2;
-  unsigned char *cp1;
-  unsigned char *cp2;
+  const unsigned char *cp1;
+  const unsigned char *cp2;
 
   /* Take care of file names without directories.  We need to make sure that
      we return consistent values to qsort since some will get confused if
@@ -7678,18 +7848,18 @@ file_info_cmp (const void *p1, const void *p2)
   if ((s1->path == s1->fname || s2->path == s2->fname))
     return (s2->path == s2->fname) - (s1->path == s1->fname);
 
-  cp1 = (unsigned char *) s1->path;
-  cp2 = (unsigned char *) s2->path;
+  cp1 = (const unsigned char *) s1->path;
+  cp2 = (const unsigned char *) s2->path;
 
   while (1)
     {
       ++cp1;
       ++cp2;
       /* Reached the end of the first path?  If so, handle like above.  */
-      if ((cp1 == (unsigned char *) s1->fname)
-         || (cp2 == (unsigned char *) s2->fname))
-       return ((cp2 == (unsigned char *) s2->fname)
-               - (cp1 == (unsigned char *) s1->fname));
+      if ((cp1 == (const unsigned char *) s1->fname)
+         || (cp2 == (const unsigned char *) s2->fname))
+       return ((cp2 == (const unsigned char *) s2->fname)
+               - (cp1 == (const unsigned char *) s1->fname));
 
       /* Character of current path component the same?  */
       else if (*cp1 != *cp2)
@@ -8285,6 +8455,13 @@ base_type_die (tree type)
        encoding = DW_ATE_float;
       break;
 
+    case FIXED_POINT_TYPE:
+      if (TYPE_UNSIGNED (type))
+       encoding = DW_ATE_unsigned_fixed;
+      else
+       encoding = DW_ATE_signed_fixed;
+      break;
+
       /* Dwarf2 doesn't know anything about complex ints, so use
         a user defined type for it.  */
     case COMPLEX_TYPE:
@@ -8329,6 +8506,7 @@ is_base_type (tree type)
     case VOID_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case BOOLEAN_TYPE:
       return 1;
@@ -8361,7 +8539,7 @@ is_base_type (tree type)
    ERROR_MARK node.  */
 
 static inline unsigned HOST_WIDE_INT
-simple_type_size_in_bits (tree type)
+simple_type_size_in_bits (const_tree type)
 {
   if (TREE_CODE (type) == ERROR_MARK)
     return BITS_PER_WORD;
@@ -8377,7 +8555,7 @@ simple_type_size_in_bits (tree type)
    emitted as a subrange type.  */
 
 static inline bool
-is_subrange_type (tree type)
+is_subrange_type (const_tree type)
 {
   tree subtype = TREE_TYPE (type);
 
@@ -8570,7 +8748,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
      don't output a DW_TAG_typedef, since there isn't one in the
      user's program; just attach a DW_AT_name to the type.  */
   if (name
-      && (TREE_CODE (name) != TYPE_DECL || TREE_TYPE (name) == qualified_type))
+      && (TREE_CODE (name) != TYPE_DECL
+         || (TREE_TYPE (name) == qualified_type && DECL_NAME (name))))
     {
       if (TREE_CODE (name) == TYPE_DECL)
        /* Could just call add_name_and_src_coords_attributes here,
@@ -8603,7 +8782,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
    an enumerated type.  */
 
 static inline int
-type_is_enum (tree type)
+type_is_enum (const_tree type)
 {
   return TREE_CODE (type) == ENUMERAL_TYPE;
 }
@@ -8611,7 +8790,7 @@ type_is_enum (tree type)
 /* Return the DBX register number described by a given RTL node.  */
 
 static unsigned int
-dbx_reg_number (rtx rtl)
+dbx_reg_number (const_rtx rtl)
 {
   unsigned regno = REGNO (rtl);
 
@@ -8653,7 +8832,7 @@ add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
    zero if there is none.  */
 
 static dw_loc_descr_ref
-reg_loc_descriptor (rtx rtl)
+reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
 {
   rtx regs;
 
@@ -8663,28 +8842,35 @@ reg_loc_descriptor (rtx rtl)
   regs = targetm.dwarf_register_span (rtl);
 
   if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
-    return multiple_reg_loc_descriptor (rtl, regs);
+    return multiple_reg_loc_descriptor (rtl, regs, initialized);
   else
-    return one_reg_loc_descriptor (dbx_reg_number (rtl));
+    return one_reg_loc_descriptor (dbx_reg_number (rtl), initialized);
 }
 
 /* Return a location descriptor that designates a machine register for
    a given hard register number.  */
 
 static dw_loc_descr_ref
-one_reg_loc_descriptor (unsigned int regno)
+one_reg_loc_descriptor (unsigned int regno, enum var_init_status initialized)
 {
+  dw_loc_descr_ref reg_loc_descr;
   if (regno <= 31)
-    return new_loc_descr (DW_OP_reg0 + regno, 0, 0);
+    reg_loc_descr = new_loc_descr (DW_OP_reg0 + regno, 0, 0);
   else
-    return new_loc_descr (DW_OP_regx, regno, 0);
+    reg_loc_descr = new_loc_descr (DW_OP_regx, regno, 0);
+
+  if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&reg_loc_descr, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
+
+  return reg_loc_descr;
 }
 
 /* Given an RTL of a register, return a location descriptor that
    designates a value that spans more than one register.  */
 
 static dw_loc_descr_ref
-multiple_reg_loc_descriptor (rtx rtl, rtx regs)
+multiple_reg_loc_descriptor (rtx rtl, rtx regs, 
+                            enum var_init_status initialized)
 {
   int nregs, size, i;
   unsigned reg;
@@ -8712,7 +8898,8 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
        {
          dw_loc_descr_ref t;
 
-         t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg));
+         t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg),
+                                     VAR_INIT_STATUS_INITIALIZED);
          add_loc_descr (&loc_result, t);
          add_loc_descr_op_piece (&loc_result, size);
          ++reg;
@@ -8731,11 +8918,15 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
     {
       dw_loc_descr_ref t;
 
-      t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)));
+      t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)),
+                                 VAR_INIT_STATUS_INITIALIZED);
       add_loc_descr (&loc_result, t);
       size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
       add_loc_descr_op_piece (&loc_result, size);
     }
+
+  if (loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
   return loc_result;
 }
 
@@ -8781,9 +8972,11 @@ int_loc_descriptor (HOST_WIDE_INT i)
 /* Return a location descriptor that designates a base+offset location.  */
 
 static dw_loc_descr_ref
-based_loc_descr (rtx reg, HOST_WIDE_INT offset)
+based_loc_descr (rtx reg, HOST_WIDE_INT offset,
+                enum var_init_status initialized)
 {
   unsigned int regno;
+  dw_loc_descr_ref result;
 
   /* We only use "frame base" when we're sure we're talking about the
      post-prologue local stack frame.  We do this by *not* running
@@ -8810,15 +9003,20 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset)
 
   regno = dbx_reg_number (reg);
   if (regno <= 31)
-    return new_loc_descr (DW_OP_breg0 + regno, offset, 0);
+    result = new_loc_descr (DW_OP_breg0 + regno, offset, 0);
   else
-    return new_loc_descr (DW_OP_bregx, regno, offset);
+    result = new_loc_descr (DW_OP_bregx, regno, offset);
+
+  if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
+
+  return result;
 }
 
 /* Return true if this RTL expression describes a base+offset calculation.  */
 
 static inline int
-is_based_loc (rtx rtl)
+is_based_loc (const_rtx rtl)
 {
   return (GET_CODE (rtl) == PLUS
          && ((REG_P (XEXP (rtl, 0))
@@ -8830,7 +9028,8 @@ is_based_loc (rtx rtl)
    used to form the address of a memory location.  */
 
 static dw_loc_descr_ref
-concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
+concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode,
+                           enum var_init_status initialized)
 {
   unsigned int i;
   dw_loc_descr_ref cc_loc_result = NULL;
@@ -8841,7 +9040,7 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
       dw_loc_descr_ref ref;
       rtx x = XVECEXP (concatn, 0, i);
 
-      ref = mem_loc_descriptor (x, mode);
+      ref = mem_loc_descriptor (x, mode, VAR_INIT_STATUS_INITIALIZED);
       if (ref == NULL)
        return NULL;
 
@@ -8849,6 +9048,9 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
       add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
     }
 
+  if (cc_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
+
   return cc_loc_result;
 }
 
@@ -8871,7 +9073,8 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
    Return 0 if we can't represent the location.  */
 
 static dw_loc_descr_ref
-mem_loc_descriptor (rtx rtl, enum machine_mode mode)
+mem_loc_descriptor (rtx rtl, enum machine_mode mode,
+                   enum var_init_status initialized)
 {
   dw_loc_descr_ref mem_loc_result = NULL;
   enum dwarf_location_atom op;
@@ -8918,11 +9121,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
         memory) so DWARF consumers need to be aware of the subtle
         distinction between OP_REG and OP_BASEREG.  */
       if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
-       mem_loc_result = based_loc_descr (rtl, 0);
+       mem_loc_result = based_loc_descr (rtl, 0, VAR_INIT_STATUS_INITIALIZED);
       break;
 
     case MEM:
-      mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
+      mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
+                                          VAR_INIT_STATUS_INITIALIZED);
       if (mem_loc_result != 0)
        add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
       break;
@@ -8989,10 +9193,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
     plus:
       if (is_based_loc (rtl))
        mem_loc_result = based_loc_descr (XEXP (rtl, 0),
-                                         INTVAL (XEXP (rtl, 1)));
+                                         INTVAL (XEXP (rtl, 1)),
+                                         VAR_INIT_STATUS_INITIALIZED);
       else
        {
-         mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
+         mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode,
+                                              VAR_INIT_STATUS_INITIALIZED);
          if (mem_loc_result == 0)
            break;
 
@@ -9004,7 +9210,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
          else
            {
              add_loc_descr (&mem_loc_result,
-                            mem_loc_descriptor (XEXP (rtl, 1), mode));
+                            mem_loc_descriptor (XEXP (rtl, 1), mode,
+                                                VAR_INIT_STATUS_INITIALIZED));
              add_loc_descr (&mem_loc_result,
                             new_loc_descr (DW_OP_plus, 0, 0));
            }
@@ -9031,8 +9238,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
 
     do_binop:
       {
-       dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode);
-       dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode);
+       dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
+                                                  VAR_INIT_STATUS_INITIALIZED);
+       dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
+                                                  VAR_INIT_STATUS_INITIALIZED);
 
        if (op0 == 0 || op1 == 0)
          break;
@@ -9048,13 +9257,17 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
       break;
 
     case CONCATN:
-      mem_loc_result = concatn_mem_loc_descriptor (rtl, mode);
+      mem_loc_result = concatn_mem_loc_descriptor (rtl, mode, 
+                                                  VAR_INIT_STATUS_INITIALIZED);
       break;
 
     default:
       gcc_unreachable ();
     }
 
+  if (mem_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
+
   return mem_loc_result;
 }
 
@@ -9062,11 +9275,11 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
    This is typically a complex variable.  */
 
 static dw_loc_descr_ref
-concat_loc_descriptor (rtx x0, rtx x1)
+concat_loc_descriptor (rtx x0, rtx x1, enum var_init_status initialized)
 {
   dw_loc_descr_ref cc_loc_result = NULL;
-  dw_loc_descr_ref x0_ref = loc_descriptor (x0);
-  dw_loc_descr_ref x1_ref = loc_descriptor (x1);
+  dw_loc_descr_ref x0_ref = loc_descriptor (x0, VAR_INIT_STATUS_INITIALIZED);
+  dw_loc_descr_ref x1_ref = loc_descriptor (x1, VAR_INIT_STATUS_INITIALIZED);
 
   if (x0_ref == 0 || x1_ref == 0)
     return 0;
@@ -9077,6 +9290,9 @@ concat_loc_descriptor (rtx x0, rtx x1)
   add_loc_descr (&cc_loc_result, x1_ref);
   add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
 
+  if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
+
   return cc_loc_result;
 }
 
@@ -9084,7 +9300,7 @@ concat_loc_descriptor (rtx x0, rtx x1)
    locations.  */
 
 static dw_loc_descr_ref
-concatn_loc_descriptor (rtx concatn)
+concatn_loc_descriptor (rtx concatn, enum var_init_status initialized)
 {
   unsigned int i;
   dw_loc_descr_ref cc_loc_result = NULL;
@@ -9095,7 +9311,7 @@ concatn_loc_descriptor (rtx concatn)
       dw_loc_descr_ref ref;
       rtx x = XVECEXP (concatn, 0, i);
 
-      ref = loc_descriptor (x);
+      ref = loc_descriptor (x, VAR_INIT_STATUS_INITIALIZED);
       if (ref == NULL)
        return NULL;
 
@@ -9103,6 +9319,9 @@ concatn_loc_descriptor (rtx concatn)
       add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
     }
 
+  if (cc_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
+    add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
+
   return cc_loc_result;
 }
 
@@ -9115,7 +9334,7 @@ concatn_loc_descriptor (rtx concatn)
    If we don't know how to describe it, return 0.  */
 
 static dw_loc_descr_ref
-loc_descriptor (rtx rtl)
+loc_descriptor (rtx rtl, enum var_init_status initialized)
 {
   dw_loc_descr_ref loc_result = NULL;
 
@@ -9132,26 +9351,28 @@ loc_descriptor (rtx rtl)
       /* ... fall through ...  */
 
     case REG:
-      loc_result = reg_loc_descriptor (rtl);
+      loc_result = reg_loc_descriptor (rtl, initialized);
       break;
 
     case MEM:
-      loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
+      loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
+                                      initialized);
       break;
 
     case CONCAT:
-      loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
+      loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1),
+                                         initialized);
       break;
 
     case CONCATN:
-      loc_result = concatn_loc_descriptor (rtl);
+      loc_result = concatn_loc_descriptor (rtl, initialized);
       break;
 
     case VAR_LOCATION:
       /* Single part.  */
       if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
        {
-         loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0));
+         loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), initialized);
          break;
        }
 
@@ -9166,14 +9387,16 @@ loc_descriptor (rtx rtl)
        int i;
 
        /* Create the first one, so we have something to add to.  */
-       loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0));
+       loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
+                                    initialized);
        mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
        add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
        for (i = 1; i < num_elem; i++)
          {
            dw_loc_descr_ref temp;
 
-           temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0));
+           temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
+                                  initialized);
            add_loc_descr (&loc_result, temp);
            mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
            add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
@@ -9305,7 +9528,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
 
            /* Certain constructs can only be represented at top-level.  */
            if (want_address == 2)
-             return loc_descriptor (rtl);
+             return loc_descriptor (rtl, VAR_INIT_STATUS_INITIALIZED);
 
            mode = GET_MODE (rtl);
            if (MEM_P (rtl))
@@ -9313,7 +9536,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
                rtl = XEXP (rtl, 0);
                have_address = 1;
              }
-           ret = mem_loc_descriptor (rtl, mode);
+           ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
          }
       }
       break;
@@ -9394,7 +9617,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
          return 0;
        mode = GET_MODE (rtl);
        rtl = XEXP (rtl, 0);
-       ret = mem_loc_descriptor (rtl, mode);
+       ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
        have_address = 1;
        break;
       }
@@ -9642,7 +9865,7 @@ ceiling (HOST_WIDE_INT value, unsigned int boundary)
    ERROR_MARK node.  */
 
 static inline tree
-field_type (tree decl)
+field_type (const_tree decl)
 {
   tree type;
 
@@ -9661,13 +9884,13 @@ field_type (tree decl)
    be an ERROR_MARK node.  */
 
 static inline unsigned
-simple_type_align_in_bits (tree type)
+simple_type_align_in_bits (const_tree type)
 {
   return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;
 }
 
 static inline unsigned
-simple_decl_align_in_bits (tree decl)
+simple_decl_align_in_bits (const_tree decl)
 {
   return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
 }
@@ -9698,7 +9921,7 @@ round_up_to_align (HOST_WIDE_INT t, unsigned int align)
    just yet).  */
 
 static HOST_WIDE_INT
-field_byte_offset (tree decl)
+field_byte_offset (const_tree decl)
 {
   HOST_WIDE_INT object_offset_in_bits;
   HOST_WIDE_INT bitpos_int;
@@ -9964,7 +10187,7 @@ extract_int (const unsigned char *src, unsigned int size)
 /* Writes floating point values to dw_vec_const array.  */
 
 static void
-insert_float (rtx rtl, unsigned char *array)
+insert_float (const_rtx rtl, unsigned char *array)
 {
   REAL_VALUE_TYPE rv;
   long val[4];
@@ -10145,9 +10368,12 @@ reference_to_unused (tree * tp, int * walk_subtrees,
     return *tp;
   else if (!flag_unit_at_a_time)
     return NULL_TREE;
+  /* ???  The C++ FE emits debug information for using decls, so
+     putting gcc_unreachable here falls over.  See PR31899.  For now
+     be conservative.  */
   else if (!cgraph_global_info_ready
           && (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
-    gcc_unreachable ();
+    return *tp;
   else if (DECL_P (*tp) && TREE_CODE (*tp) == VAR_DECL)
     {
       struct varpool_node *node = varpool_node (*tp);
@@ -10161,6 +10387,8 @@ reference_to_unused (tree * tp, int * walk_subtrees,
       if (!node->output)
        return *tp;
     }
+  else if (TREE_CODE (*tp) == STRING_CST && !TREE_ASM_WRITTEN (*tp))
+    return *tp;
 
   return NULL_TREE;
 }
@@ -10205,6 +10433,43 @@ rtl_for_decl_init (tree init, tree type)
   else if (initializer_constant_valid_p (init, type)
           && ! walk_tree (&init, reference_to_unused, NULL, NULL))
     {
+      /* Convert vector CONSTRUCTOR initializers to VECTOR_CST if
+        possible.  */
+      if (TREE_CODE (type) == VECTOR_TYPE)
+       switch (TREE_CODE (init))
+         {
+         case VECTOR_CST:
+           break;
+         case CONSTRUCTOR:
+           if (TREE_CONSTANT (init))
+             {
+               VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (init);
+               bool constant_p = true;
+               tree value;
+               unsigned HOST_WIDE_INT ix;
+
+               /* Even when ctor is constant, it might contain non-*_CST
+                  elements (e.g. { 1.0/0.0 - 1.0/0.0, 0.0 }) and those don't
+                  belong into VECTOR_CST nodes.  */
+               FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
+                 if (!CONSTANT_CLASS_P (value))
+                   {
+                     constant_p = false;
+                     break;
+                   }
+
+               if (constant_p)
+                 {
+                   init = build_vector_from_ctor (type, elts);
+                   break;
+                 }
+             }
+           /* FALLTHRU */
+
+         default:
+           return NULL;
+         }
+
       rtl = expand_expr (init, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
 
       /* If expand_expr returns a MEM, it wasn't immediate.  */
@@ -10424,7 +10689,7 @@ rtl_for_decl_location (tree decl)
    XXX: If you split a variable across multiple sections, we won't notice.  */
 
 static const char *
-secname_for_decl (tree decl)
+secname_for_decl (const_tree decl)
 {
   const char *secname;
 
@@ -10481,6 +10746,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
       const char *endname, *secname;
       dw_loc_list_ref list;
       rtx varloc;
+      enum var_init_status initialized;
 
       /* Now that we know what section we are using for a base,
         actually construct the list of locations.
@@ -10497,7 +10763,12 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
       varloc = NOTE_VAR_LOCATION (node->var_loc_note);
       secname = secname_for_decl (decl);
 
-      list = new_loc_list (loc_descriptor (varloc),
+      if (NOTE_VAR_LOCATION_LOC (node->var_loc_note))
+       initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
+      else
+       initialized = VAR_INIT_STATUS_INITIALIZED;
+
+      list = new_loc_list (loc_descriptor (varloc, initialized),
                           node->label, node->next->label, secname, 1);
       node = node->next;
 
@@ -10506,8 +10777,11 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
          {
            /* The variable has a location between NODE->LABEL and
               NODE->NEXT->LABEL.  */
+           enum var_init_status initialized =
+             NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
            varloc = NOTE_VAR_LOCATION (node->var_loc_note);
-           add_loc_descr_to_loc_list (&list, loc_descriptor (varloc),
+           add_loc_descr_to_loc_list (&list, 
+                                      loc_descriptor (varloc, initialized),
                                       node->label, node->next->label, secname);
          }
 
@@ -10516,6 +10790,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
       if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
        {
          char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
+         enum var_init_status initialized =
+           NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
 
          varloc = NOTE_VAR_LOCATION (node->var_loc_note);
          if (!current_function_decl)
@@ -10526,7 +10802,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
                                           current_function_funcdef_no);
              endname = ggc_strdup (label_id);
            }
-         add_loc_descr_to_loc_list (&list, loc_descriptor (varloc),
+         add_loc_descr_to_loc_list (&list, 
+                                    loc_descriptor (varloc, initialized),
                                     node->label, endname, secname);
        }
 
@@ -10550,8 +10827,10 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
      location list, try generating a location from that.  */
   if (loc_list && loc_list->first)
     {
+      enum var_init_status status;
       node = loc_list->first;
-      descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note));
+      status = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
+      descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note), status);
       if (descr)
        {
          add_AT_location_description (die, attr, descr);
@@ -10729,7 +11008,7 @@ add_comp_dir_attribute (dw_die_ref die)
 {
   const char *wd = get_src_pwd ();
   if (wd != NULL)
-    add_AT_string (die, DW_AT_comp_dir, wd);
+    add_AT_string (die, DW_AT_comp_dir, remap_debug_filename (wd));
 }
 
 /* Given a tree node describing an array bound (either lower or upper) output
@@ -11102,7 +11381,8 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
          && TREE_PUBLIC (decl)
          && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
          && !DECL_ABSTRACT (decl)
-         && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)))
+         && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+         && !is_fortran ())
        add_AT_string (die, DW_AT_MIPS_linkage_name,
                       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
     }
@@ -11217,6 +11497,8 @@ class_or_namespace_scope_p (dw_die_ref context_die)
 {
   return (context_die
          && (context_die->die_tag == DW_TAG_structure_type
+             || context_die->die_tag == DW_TAG_class_type
+             || context_die->die_tag == DW_TAG_interface_type
              || context_die->die_tag == DW_TAG_union_type
              || context_die->die_tag == DW_TAG_namespace));
 }
@@ -11232,11 +11514,11 @@ add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
 
-  /* ??? If this type is an unnamed subrange type of an integral or
-     floating-point type, use the inner type.  This is because we have no
+  /* ??? If this type is an unnamed subrange type of an integral, floating-point
+     or fixed-point type, use the inner type.  This is because we have no
      support for unnamed types in base_type_die.  This can happen if this is
      an Ada subrange type.  Correct solution is emit a subrange type die.  */
-  if ((code == INTEGER_TYPE || code == REAL_TYPE)
+  if ((code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE)
       && TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0)
     type = TREE_TYPE (type), code = TREE_CODE (type);
 
@@ -11259,11 +11541,20 @@ add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
 /* Given an object die, add the calling convention attribute for the
    function call type.  */
 static void
-add_calling_convention_attribute (dw_die_ref subr_die, tree type)
+add_calling_convention_attribute (dw_die_ref subr_die, tree decl)
 {
   enum dwarf_calling_convention value = DW_CC_normal;
 
-  value = targetm.dwarf_calling_convention (type);
+  value = targetm.dwarf_calling_convention (TREE_TYPE (decl));
+
+  /* DWARF doesn't provide a way to identify a program's source-level
+     entry point.  DW_AT_calling_convention attributes are only meant
+     to describe functions' calling conventions.  However, lacking a
+     better way to signal the Fortran main program, we use this for the
+     time being, following existing custom.  */
+  if (is_fortran ()
+      && !strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), "MAIN__"))
+    value = DW_CC_program;
 
   /* Only add the attribute if the backend requests it, and
      is not DW_CC_normal.  */
@@ -11276,7 +11567,7 @@ add_calling_convention_attribute (dw_die_ref subr_die, tree type)
    was declared without a tag.  */
 
 static const char *
-type_tag (tree type)
+type_tag (const_tree type)
 {
   const char *name = 0;
 
@@ -11314,7 +11605,7 @@ type_tag (tree type)
    for bit field types.  */
 
 static inline tree
-member_declared_type (tree member)
+member_declared_type (const_tree member)
 {
   return (DECL_BIT_FIELD_TYPE (member)
          ? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member));
@@ -11371,6 +11662,12 @@ gen_array_type_die (tree type, dw_die_ref context_die)
       add_AT_flag (array_die, DW_AT_GNU_vector, 1);
     }
 
+  /* For Fortran multidimensional arrays use DW_ORD_col_major ordering.  */
+  if (is_fortran ()
+      && TREE_CODE (type) == ARRAY_TYPE
+      && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
+    add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+
 #if 0
   /* We default the array ordering.  SDB will probably do
      the right things even if DW_AT_ordering is not present.  It's not even
@@ -11411,6 +11708,168 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
+static dw_loc_descr_ref
+descr_info_loc (tree val, tree base_decl)
+{
+  HOST_WIDE_INT size;
+  dw_loc_descr_ref loc, loc2;
+  enum dwarf_location_atom op;
+
+  if (val == base_decl)
+    return new_loc_descr (DW_OP_push_object_address, 0, 0);
+
+  switch (TREE_CODE (val))
+    {
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
+    case INTEGER_CST:
+      if (host_integerp (val, 0))
+       return int_loc_descriptor (tree_low_cst (val, 0));
+      break;
+    case INDIRECT_REF:
+      size = int_size_in_bytes (TREE_TYPE (val));
+      if (size < 0)
+       break;
+      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
+      if (!loc)
+       break;
+      if (size == DWARF2_ADDR_SIZE)
+       add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
+      else
+       add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
+      return loc;
+    case POINTER_PLUS_EXPR:
+    case PLUS_EXPR:
+      if (host_integerp (TREE_OPERAND (val, 1), 1)
+         && (unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (val, 1), 1)
+            < 16384)
+       {
+         loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
+         if (!loc)
+           break;
+         add_loc_descr (&loc,
+                        new_loc_descr (DW_OP_plus_uconst,
+                                       tree_low_cst (TREE_OPERAND (val, 1),
+                                                     1), 0));
+       }
+      else
+       {
+         op = DW_OP_plus;
+       do_binop:
+         loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
+         if (!loc)
+           break;
+         loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
+         if (!loc2)
+           break;
+         add_loc_descr (&loc, loc2);
+         add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
+       }
+      return loc;
+    case MINUS_EXPR:
+      op = DW_OP_minus;
+      goto do_binop;
+    case MULT_EXPR:
+      op = DW_OP_mul;
+      goto do_binop;
+    case EQ_EXPR:
+      op = DW_OP_eq;
+      goto do_binop;
+    case NE_EXPR:
+      op = DW_OP_ne;
+      goto do_binop;
+    default:
+      break;
+    }
+  return NULL;
+}
+
+static void
+add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
+                     tree val, tree base_decl)
+{
+  dw_loc_descr_ref loc;
+
+  if (host_integerp (val, 0))
+    {
+      add_AT_unsigned (die, attr, tree_low_cst (val, 0));
+      return;
+    }
+
+  loc = descr_info_loc (val, base_decl);
+  if (!loc)
+    return;
+
+  add_AT_loc (die, attr, loc);
+}
+
+/* This routine generates DIE for array with hidden descriptor, details
+   are filled into *info by a langhook.  */
+
+static void
+gen_descr_array_type_die (tree type, struct array_descr_info *info,
+                         dw_die_ref context_die)
+{
+  dw_die_ref scope_die = scope_die_for (type, context_die);
+  dw_die_ref array_die;
+  int dim;
+
+  array_die = new_die (DW_TAG_array_type, scope_die, type);
+  add_name_attribute (array_die, type_tag (type));
+  equate_type_number_to_die (type, array_die);
+
+  /* For Fortran multidimensional arrays use DW_ORD_col_major ordering.  */
+  if (is_fortran ()
+      && info->ndimensions >= 2)
+    add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+
+  if (info->data_location)
+    add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
+                         info->base_decl);
+  if (info->associated)
+    add_descr_info_field (array_die, DW_AT_associated, info->associated,
+                         info->base_decl);
+  if (info->allocated)
+    add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
+                         info->base_decl);
+
+  for (dim = 0; dim < info->ndimensions; dim++)
+    {
+      dw_die_ref subrange_die
+       = new_die (DW_TAG_subrange_type, array_die, NULL);
+
+      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))
+           ;
+         else
+           add_descr_info_field (subrange_die, DW_AT_lower_bound,
+                                 info->dimen[dim].lower_bound,
+                                 info->base_decl);
+       }
+      if (info->dimen[dim].upper_bound)
+       add_descr_info_field (subrange_die, DW_AT_upper_bound,
+                             info->dimen[dim].upper_bound,
+                             info->base_decl);
+      if (info->dimen[dim].stride)
+       add_descr_info_field (subrange_die, DW_AT_byte_stride,
+                             info->dimen[dim].stride,
+                             info->base_decl);
+    }
+
+  gen_type_die (info->element_type, context_die);
+  add_type_attribute (array_die, info->element_type, 0, 0, context_die);
+
+  if (get_AT (array_die, DW_AT_name))
+    add_pubtype (type, array_die);
+}
+
 #if 0
 static void
 gen_entry_point_die (tree decl, dw_die_ref context_die)
@@ -11458,12 +11917,36 @@ gen_inlined_enumeration_type_die (tree type, dw_die_ref context_die)
   add_abstract_origin_attribute (type_die, type);
 }
 
+/* Determine what tag to use for a record type.  */
+
+static enum dwarf_tag
+record_type_tag (tree type)
+{
+  if (! lang_hooks.types.classify_record)
+    return DW_TAG_structure_type;
+
+  switch (lang_hooks.types.classify_record (type))
+    {
+    case RECORD_IS_STRUCT:
+      return DW_TAG_structure_type;
+
+    case RECORD_IS_CLASS:
+      return DW_TAG_class_type;
+
+    case RECORD_IS_INTERFACE:
+      return DW_TAG_interface_type;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Generate a DIE to represent an inlined instance of a structure type.  */
 
 static void
 gen_inlined_structure_type_die (tree type, dw_die_ref context_die)
 {
-  dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type);
+  dw_die_ref type_die = new_die (record_type_tag (type), context_die, type);
 
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
@@ -11578,8 +12061,11 @@ gen_formal_parameter_die (tree node, dw_die_ref context_die)
        add_abstract_origin_attribute (parm_die, origin);
       else
        {
+         tree type = TREE_TYPE (node);
          add_name_and_src_coords_attributes (parm_die, node);
-         add_type_attribute (parm_die, TREE_TYPE (node),
+         if (DECL_BY_REFERENCE (node))
+           type = TREE_TYPE (type);
+         add_type_attribute (parm_die, type,
                              TREE_READONLY (node),
                              TREE_THIS_VOLATILE (node),
                              context_die);
@@ -11722,7 +12208,6 @@ dwarf2out_abstract_function (tree decl)
 {
   dw_die_ref old_die;
   tree save_fn;
-  struct function *save_cfun;
   tree context;
   int was_abstract = DECL_ABSTRACT (decl);
 
@@ -11746,9 +12231,8 @@ dwarf2out_abstract_function (tree decl)
 
   /* Pretend we've just finished compiling this function.  */
   save_fn = current_function_decl;
-  save_cfun = cfun;
   current_function_decl = decl;
-  cfun = DECL_STRUCT_FUNCTION (decl);
+  push_cfun (DECL_STRUCT_FUNCTION (decl));
 
   set_decl_abstract_flags (decl, 1);
   dwarf2out_decl (decl);
@@ -11756,7 +12240,7 @@ dwarf2out_abstract_function (tree decl)
     set_decl_abstract_flags (decl, 0);
 
   current_function_decl = save_fn;
-  cfun = save_cfun;
+  pop_cfun ();
 }
 
 /* Helper function of premark_used_types() which gets called through
@@ -11942,6 +12426,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
            add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined);
        }
 
+      if (DECL_DECLARED_INLINE_P (decl)
+         && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
+       add_AT_flag (subr_die, DW_AT_artificial, 1);
+
       equate_decl_number_to_die (decl, subr_die);
     }
   else if (!DECL_EXTERNAL (decl))
@@ -12111,7 +12599,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 #endif
     }
   /* Add the calling convention attribute if requested.  */
-  add_calling_convention_attribute (subr_die, TREE_TYPE (decl));
+  add_calling_convention_attribute (subr_die, decl);
 
 }
 
@@ -12181,8 +12669,14 @@ gen_variable_die (tree decl, dw_die_ref context_die)
     }
   else
     {
+      tree type = TREE_TYPE (decl);
+      if ((TREE_CODE (decl) == PARM_DECL
+          || TREE_CODE (decl) == RESULT_DECL)
+         && DECL_BY_REFERENCE (decl))
+       type = TREE_TYPE (type);
+
       add_name_and_src_coords_attributes (var_die, decl);
-      add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
+      add_type_attribute (var_die, type, TREE_READONLY (decl),
                          TREE_THIS_VOLATILE (decl), context_die);
 
       if (TREE_PUBLIC (decl))
@@ -12272,7 +12766,7 @@ add_call_src_coords_attributes (tree stmt, dw_die_ref die)
    first subblock's abstract origin is the function's outermost block,
    then we're looking at the main entry point.  */
 static bool
-is_inlined_entry_point (tree stmt)
+is_inlined_entry_point (const_tree stmt)
 {
   tree decl, block;
 
@@ -12653,7 +13147,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
       dw_die_ref old_die = type_die;
 
       type_die = new_die (TREE_CODE (type) == RECORD_TYPE
-                         ? DW_TAG_structure_type : DW_TAG_union_type,
+                         ? record_type_tag (type) : DW_TAG_union_type,
                          scope_die, type);
       equate_type_number_to_die (type, type_die);
       if (old_die)
@@ -12776,6 +13270,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
                                enum debug_info_usage usage)
 {
   int need_pop;
+  struct array_descr_info info;
 
   if (type == NULL_TREE || type == error_mark_node)
     return;
@@ -12794,6 +13289,16 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       return;
     }
 
+  /* If this is an array type with hidden descriptor, handle it first.  */
+  if (!TREE_ASM_WRITTEN (type)
+      && lang_hooks.types.get_array_descr_info
+      && lang_hooks.types.get_array_descr_info (type, &info))
+    {
+      gen_descr_array_type_die (type, &info, context_die);
+      TREE_ASM_WRITTEN (type) = 1;
+      return;
+    }
+
   /* We are going to output a DIE to represent the unqualified version
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
@@ -12913,6 +13418,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     case VOID_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case BOOLEAN_TYPE:
       /* No DIEs needed for fundamental types.  */
@@ -13126,7 +13632,7 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
 /* Is this a typedef we can avoid emitting?  */
 
 static inline int
-is_redundant_typedef (tree decl)
+is_redundant_typedef (const_tree decl)
 {
   if (TYPE_DECL_IS_STUB (decl))
     return 1;
@@ -13409,7 +13915,8 @@ gen_decl_die (tree decl, dw_die_ref context_die)
         was generated within the original definition of an inline function) we
         have to generate a special (abbreviated) DW_TAG_structure_type,
         DW_TAG_union_type, or DW_TAG_enumeration_type DIE here.  */
-      if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE)
+      if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE
+         && is_tagged_type (TREE_TYPE (decl)))
        {
          gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die);
          break;
@@ -13436,7 +13943,10 @@ gen_decl_die (tree decl, dw_die_ref context_die)
 
       /* Output any DIEs that are needed to specify the type of this data
         object.  */
-      gen_type_die (TREE_TYPE (decl), context_die);
+      if (TREE_CODE (decl) == RESULT_DECL && DECL_BY_REFERENCE (decl))
+       gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
+      else
+       gen_type_die (TREE_TYPE (decl), context_die);
 
       /* And its containing type.  */
       origin = decl_class_context (decl);
@@ -13470,7 +13980,10 @@ gen_decl_die (tree decl, dw_die_ref context_die)
       break;
 
     case PARM_DECL:
-      gen_type_die (TREE_TYPE (decl), context_die);
+      if (DECL_BY_REFERENCE (decl))
+       gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
+      else
+       gen_type_die (TREE_TYPE (decl), context_die);
       gen_formal_parameter_die (decl, context_die);
       break;
 
@@ -13736,7 +14249,7 @@ dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum)
    we may end up calling them anyway.  */
 
 static bool
-dwarf2out_ignore_block (tree block)
+dwarf2out_ignore_block (const_tree block)
 {
   tree decl;
 
@@ -13822,7 +14335,8 @@ maybe_emit_file (struct dwarf_file_data * fd)
       if (DWARF2_ASM_LINE_DEBUG_INFO)
        {
          fprintf (asm_out_file, "\t.file %u ", fd->emitted_number);
-         output_quoted_string (asm_out_file, fd->filename);
+         output_quoted_string (asm_out_file,
+                               remap_debug_filename (fd->filename));
          fputc ('\n', asm_out_file);
        }
     }
@@ -13892,6 +14406,8 @@ dwarf2out_begin_function (tree fun)
 
   if (function_section (fun) != text_section)
     have_multiple_function_sections = true;
+
+  dwarf2out_note_section_used ();
 }
 
 /* Output a label to mark the beginning of a source code line entry
@@ -13989,7 +14505,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename)
       dw_die_ref bincl_die;
 
       bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
-      add_AT_string (bincl_die, DW_AT_name, filename);
+      add_AT_string (bincl_die, DW_AT_name, remap_debug_filename (filename));
     }
 
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
@@ -14164,7 +14680,8 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
   if (flag_reorder_blocks_and_partition)
     {
-      switch_to_section (unlikely_text_section ());
+      cold_text_section = unlikely_text_section ();
+      switch_to_section (cold_text_section);
       ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
     }
 }
@@ -14304,6 +14821,7 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
     case DW_TAG_class_type:
+    case DW_TAG_interface_type:
     case DW_TAG_friend:
     case DW_TAG_variant_part:
     case DW_TAG_enumeration_type:
@@ -14448,7 +14966,7 @@ file_table_relative_p (void ** slot, void *param)
 {
   bool *p = param;
   struct dwarf_file_data *d = *slot;
-  if (d->emitted_number && !IS_ABSOLUTE_PATH (d->filename))
+  if (!IS_ABSOLUTE_PATH (d->filename))
     {
       *p = true;
       return 0;
@@ -14467,7 +14985,7 @@ dwarf2out_finish (const char *filename)
 
   /* Add the name for the main input file now.  We delayed this from
      dwarf2out_init to avoid complications with PCH.  */
-  add_name_attribute (comp_unit_die, filename);
+  add_name_attribute (comp_unit_die, remap_debug_filename (filename));
   if (!IS_ABSOLUTE_PATH (filename))
     add_comp_dir_attribute (comp_unit_die);
   else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
@@ -14570,10 +15088,43 @@ dwarf2out_finish (const char *filename)
       add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
     }
 
-  /* If it wasn't, we need to give .debug_loc and .debug_ranges an appropriate
-     "base address".  Use zero so that these addresses become absolute.  */
-  else if (have_location_lists || ranges_table_in_use)
-    add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx);
+  else
+    {
+      unsigned fde_idx = 0;
+
+      /* We need to give .debug_loc and .debug_ranges an appropriate
+        "base address".  Use zero so that these addresses become
+        absolute.  Historically, we've emitted the unexpected
+        DW_AT_entry_pc instead of DW_AT_low_pc for this purpose.
+        Emit both to give time for other tools to adapt.  */
+      add_AT_addr (comp_unit_die, DW_AT_low_pc, const0_rtx);
+      add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx);
+
+      add_AT_range_list (comp_unit_die, DW_AT_ranges,
+                        add_ranges_by_labels (text_section_label,
+                                              text_end_label));
+      if (flag_reorder_blocks_and_partition)
+       add_ranges_by_labels (cold_text_section_label,
+                             cold_end_label);
+
+      for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++)
+       {
+         dw_fde_ref fde = &fde_table[fde_idx];
+
+         if (fde->dw_fde_switched_sections)
+           {
+             add_ranges_by_labels (fde->dw_fde_hot_section_label,
+                                   fde->dw_fde_hot_section_end_label);
+             add_ranges_by_labels (fde->dw_fde_unlikely_section_label,
+                                   fde->dw_fde_unlikely_section_end_label);
+           }
+         else
+           add_ranges_by_labels (fde->dw_fde_begin,
+                                 fde->dw_fde_end);
+       }
+
+      add_ranges (NULL);
+    }
 
   /* Output location list section if necessary.  */
   if (have_location_lists)