OSDN Git Service

* config/cris/cris.md ("movsi"): Fix typo in last change.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 6c714f9..a54e517 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 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007 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).
@@ -34,6 +34,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 +95,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 \
@@ -156,6 +161,7 @@ static GTY(()) section *debug_macinfo_section;
 static GTY(()) section *debug_line_section;
 static GTY(()) section *debug_loc_section;
 static GTY(()) section *debug_pubnames_section;
+static GTY(()) section *debug_pubtypes_section;
 static GTY(()) section *debug_str_section;
 static GTY(()) section *debug_ranges_section;
 static GTY(()) section *debug_frame_section;
@@ -346,7 +352,9 @@ static void add_fde_cfi (const char *, dw_cfi_ref);
 static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *);
 static void lookup_cfa (dw_cfa_location *);
 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 void output_cfi (dw_cfi_ref, dw_fde_ref, int);
 static void output_call_frame_info (int);
@@ -442,6 +450,17 @@ stripattributes (const char *s)
   return stripped;
 }
 
+/* MEM is a memory reference for the register size table, each element of
+   which has mode MODE.  Initialize column C as a return address column.  */
+
+static void
+init_return_column_size (enum machine_mode mode, rtx mem, unsigned int c)
+{
+  HOST_WIDE_INT offset = c * GET_MODE_SIZE (mode);
+  HOST_WIDE_INT size = GET_MODE_SIZE (Pmode);
+  emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
+}
+
 /* Generate code to initialize the register size table.  */
 
 void
@@ -456,13 +475,13 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
       int rnum = DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), 1);
-      
+
       if (rnum < DWARF_FRAME_REGISTERS)
        {
          HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (mode);
          enum machine_mode save_mode = reg_raw_mode[i];
          HOST_WIDE_INT size;
-         
+
          if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode))
            save_mode = choose_hard_reg_mode (i, 1, true);
          if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
@@ -474,27 +493,20 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
          size = GET_MODE_SIZE (save_mode);
          if (offset < 0)
            continue;
-         
+
          emit_move_insn (adjust_address (mem, mode, offset),
                          gen_int_mode (size, mode));
        }
     }
 
+  if (!wrote_return_column)
+    init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
+
 #ifdef DWARF_ALT_FRAME_RETURN_COLUMN
-  gcc_assert (wrote_return_column);
-  i = DWARF_ALT_FRAME_RETURN_COLUMN;
-  wrote_return_column = false;
-#else
-  i = DWARF_FRAME_RETURN_COLUMN;
+  init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
 #endif
 
-  if (! wrote_return_column)
-    {
-      enum machine_mode save_mode = Pmode;
-      HOST_WIDE_INT offset = i * GET_MODE_SIZE (mode);
-      HOST_WIDE_INT size = GET_MODE_SIZE (save_mode);
-      emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
-    }
+  targetm.init_dwarf_reg_sizes_extra (address);
 }
 
 /* Convert a DWARF call frame info. operation to its string name */
@@ -950,6 +962,7 @@ dwarf2out_return_reg (const char *label, unsigned int sreg)
   reg_save (label, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0);
 }
 
+#ifdef DWARF2_UNWIND_INFO
 /* Record the initial position of the return address.  RTL is
    INCOMING_RETURN_ADDR_RTX.  */
 
@@ -1007,6 +1020,7 @@ initial_return_save (rtx rtl)
   if (reg != DWARF_FRAME_RETURN_COLUMN)
     reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
 }
+#endif
 
 /* Given a SET, calculate the amount of stack adjustment it
    contains.  */
@@ -1521,13 +1535,31 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
     {
       int par_index;
       int limit = XVECLEN (expr, 0);
+      rtx elem;
+
+      /* PARALLELs have strict read-modify-write semantics, so we
+        ought to evaluate every rvalue before changing any lvalue.
+        It's cumbersome to do that in general, but there's an
+        easy approximation that is enough for all current users:
+        handle register saves before register assignments.  */
+      if (GET_CODE (expr) == PARALLEL)
+       for (par_index = 0; par_index < limit; par_index++)
+         {
+           elem = XVECEXP (expr, 0, par_index);
+           if (GET_CODE (elem) == SET
+               && MEM_P (SET_DEST (elem))
+               && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
+             dwarf2out_frame_debug_expr (elem, label);
+         }
 
       for (par_index = 0; par_index < limit; par_index++)
-       if (GET_CODE (XVECEXP (expr, 0, par_index)) == SET
-           && (RTX_FRAME_RELATED_P (XVECEXP (expr, 0, par_index))
-               || par_index == 0))
-         dwarf2out_frame_debug_expr (XVECEXP (expr, 0, par_index), label);
-
+       {
+         elem = XVECEXP (expr, 0, par_index);
+         if (GET_CODE (elem) == SET
+             && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
+             && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
+           dwarf2out_frame_debug_expr (elem, label);
+       }
       return;
     }
 
@@ -2030,7 +2062,7 @@ switch_to_eh_frame_section (void)
       /* We have no special eh_frame section.  Put the information in
         the data section and emit special labels to guide collect2.  */
       switch_to_section (data_section);
-      label = get_file_function_name ('F');
+      label = get_file_function_name ("F");
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
       targetm.asm_out.globalize_label (asm_out_file,
                                       IDENTIFIER_POINTER (label));
@@ -2195,7 +2227,7 @@ output_call_frame_info (int for_eh)
       && for_eh)
     for (i = 0; i < fde_table_in_use; i++)
       if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
-          && !fde_table[i].uses_eh_lsda
+         && !fde_table[i].uses_eh_lsda
          && ! DECL_WEAK (fde_table[i].decl))
        targetm.asm_out.unwind_label (asm_out_file, fde_table[i].decl,
                                      for_eh, /* empty */ 1);
@@ -2211,7 +2243,7 @@ output_call_frame_info (int for_eh)
       for (i = 0; i < fde_table_in_use; i++)
        if (fde_table[i].uses_eh_lsda)
          any_eh_needed = any_lsda_needed = true;
-        else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
+       else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
          any_eh_needed = true;
        else if (! fde_table[i].nothrow
                 && ! fde_table[i].all_throwers_are_sibcalls)
@@ -2281,6 +2313,7 @@ output_call_frame_info (int for_eh)
        {
          *p++ = 'P';
          augmentation_size += 1 + size_of_encoded_value (per_encoding);
+         assemble_external_libcall (eh_personality_libfunc);
        }
       if (any_lsda_needed)
        {
@@ -2399,9 +2432,9 @@ output_call_frame_info (int for_eh)
                                           "FDE initial location");
          if (fde->dw_fde_switched_sections)
            {
-             rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode, 
+             rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode,
                                      fde->dw_fde_unlikely_section_label);
-             rtx sym_ref3= gen_rtx_SYMBOL_REF (Pmode, 
+             rtx sym_ref3= gen_rtx_SYMBOL_REF (Pmode,
                                      fde->dw_fde_hot_section_label);
              SYMBOL_REF_FLAGS (sym_ref2) |= SYMBOL_FLAG_LOCAL;
              SYMBOL_REF_FLAGS (sym_ref3) |= SYMBOL_FLAG_LOCAL;
@@ -2439,7 +2472,7 @@ output_call_frame_info (int for_eh)
              dw2_asm_output_addr (DWARF2_ADDR_SIZE,
                                   fde->dw_fde_unlikely_section_label,
                                   "FDE initial location");
-             dw2_asm_output_delta (DWARF2_ADDR_SIZE, 
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE,
                                    fde->dw_fde_unlikely_section_end_label,
                                    fde->dw_fde_unlikely_section_label,
                                    "FDE address range");
@@ -3682,6 +3715,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
@@ -3755,13 +3789,24 @@ die_node;
 typedef struct pubname_struct GTY(())
 {
   dw_die_ref die;
-  char *name;
+  const char *name;
 }
 pubname_entry;
 
+DEF_VEC_O(pubname_entry);
+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.  */
@@ -3812,14 +3857,14 @@ limbo_die_node;
 /* Fixed size portion of the address range info.  */
 #define DWARF_ARANGES_HEADER_SIZE                                      \
   (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4,     \
-                DWARF2_ADDR_SIZE * 2)                                  \
+               DWARF2_ADDR_SIZE * 2)                                   \
    - DWARF_INITIAL_LENGTH_SIZE)
 
 /* Size of padding portion in the address range info.  It must be
    aligned to twice the pointer size.  */
 #define DWARF_ARANGES_PAD_SIZE \
   (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
-                DWARF2_ADDR_SIZE * 2) \
+               DWARF2_ADDR_SIZE * 2)                              \
    - (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4))
 
 /* Use assembler line directives if available.  */
@@ -3940,17 +3985,11 @@ static GTY(()) unsigned separate_line_info_table_in_use;
 
 /* A pointer to the base of a table that contains a list of publicly
    accessible names.  */
-static GTY ((length ("pubname_table_allocated"))) pubname_ref pubname_table;
+static GTY (()) VEC (pubname_entry, gc) *  pubname_table;
 
-/* Number of elements currently allocated for pubname_table.  */
-static GTY(()) unsigned pubname_table_allocated;
-
-/* Number of elements in pubname_table currently in use.  */
-static GTY(()) unsigned pubname_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
-   pubname_table.  */
-#define PUBNAME_TABLE_INCREMENT 64
+/* A pointer to the base of a table that contains a list of publicly
+   accessible types.  */
+static GTY (()) VEC (pubname_entry, gc) * pubtype_table;
 
 /* Array of dies for which we should generate .debug_arange info.  */
 static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table;
@@ -3974,6 +4013,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
@@ -4115,7 +4164,7 @@ static void calc_die_sizes (dw_die_ref);
 static void mark_dies (dw_die_ref);
 static void unmark_dies (dw_die_ref);
 static void unmark_all_dies (dw_die_ref);
-static unsigned long size_of_pubnames (void);
+static unsigned long size_of_pubnames (VEC (pubname_entry,gc) *);
 static unsigned long size_of_aranges (void);
 static enum dwarf_form value_format (dw_attr_ref);
 static void output_value_format (dw_attr_ref);
@@ -4126,15 +4175,17 @@ static void output_compilation_unit_header (void);
 static void output_comp_unit (dw_die_ref, int);
 static const char *dwarf2_name (tree, int);
 static void add_pubname (tree, dw_die_ref);
-static void output_pubnames (void);
+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_num (int);
 static unsigned int add_ranges (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 tree root_type (tree);
 static int is_base_type (tree);
 static bool is_subrange_type (tree);
 static dw_die_ref subrange_type_die (tree, dw_die_ref);
@@ -4215,7 +4266,8 @@ static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
 static dw_die_ref gen_compile_unit_die (const char *);
 static void gen_inheritance_die (tree, tree, dw_die_ref);
 static void gen_member_die (tree, dw_die_ref);
-static void gen_struct_or_union_type_die (tree, dw_die_ref);
+static void gen_struct_or_union_type_die (tree, dw_die_ref,
+                                               enum debug_info_usage);
 static void gen_subroutine_type_die (tree, dw_die_ref);
 static void gen_typedef_die (tree, dw_die_ref);
 static void gen_type_die (tree, dw_die_ref);
@@ -4327,7 +4379,7 @@ static int maybe_emit_file (struct dwarf_file_data *fd);
 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char cold_text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 
+static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -4843,7 +4895,7 @@ block_ultimate_origin (tree block)
                       ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL);
        }
       while (lookahead != NULL && lookahead != ret_val);
-      
+
       /* The block's abstract origin chain may not be the *ultimate* origin of
         the block. It could lead to a DECL that has an abstract origin set.
         If so, we want that DECL's abstract origin (which is what DECL_ORIGIN
@@ -4886,7 +4938,7 @@ add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
   /* Maybe this should be an assert?  */
   if (die == NULL)
     return;
-  
+
   if (die->die_attr == NULL)
     die->die_attr = VEC_alloc (dw_attr_node, gc, 1);
   VEC_safe_push (dw_attr_node, gc, die->die_attr, attr);
@@ -5021,9 +5073,15 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
   slot = htab_find_slot_with_hash (debug_str_hash, str,
                                   htab_hash_string (str), INSERT);
   if (*slot == NULL)
-    *slot = ggc_alloc_cleared (sizeof (struct indirect_string_node));
-  node = (struct indirect_string_node *) *slot;
-  node->str = ggc_strdup (str);
+    {
+      node = (struct indirect_string_node *)
+              ggc_alloc_cleared (sizeof (struct indirect_string_node));
+      node->str = ggc_strdup (str);
+      *slot = node;
+    }
+  else
+    node = (struct indirect_string_node *) *slot;
+
   node->refcount++;
 
   attr.dw_attr = attr_kind;
@@ -5319,7 +5377,7 @@ get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
     else if (a->dw_attr == DW_AT_specification
             || a->dw_attr == DW_AT_abstract_origin)
       spec = AT_ref (a);
-  
+
   if (spec)
     return get_AT (spec, attr_kind);
 
@@ -5417,7 +5475,7 @@ static inline bool
 is_cxx (void)
 {
   unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
-  
+
   return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus;
 }
 
@@ -5504,7 +5562,7 @@ static void
 remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
 {
   dw_die_ref c;
-  
+
   c = die->die_child;
   if (c) do {
     dw_die_ref prev = c;
@@ -5542,7 +5600,7 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 }
 
 /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
-   is the specification, to the end of PARENT's list of children.  
+   is the specification, to the end of PARENT's list of children.
    This is done by removing and re-adding it.  */
 
 static void
@@ -5563,7 +5621,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
   gcc_assert (child->die_parent == parent
              || (child->die_parent
                  == get_AT_ref (parent, DW_AT_specification)));
-  
+
   for (p = child->die_parent->die_child; ; p = p->die_sib)
     if (p->die_sib == child)
       {
@@ -5740,11 +5798,11 @@ print_die (dw_die_ref die, FILE *outfile)
   unsigned ix;
 
   print_spaces (outfile);
-  fprintf (outfile, "DIE %4lu: %s\n",
+  fprintf (outfile, "DIE %4ld: %s\n",
           die->die_offset, dwarf_tag_name (die->die_tag));
   print_spaces (outfile);
   fprintf (outfile, "  abbrev id: %lu", die->die_abbrev);
-  fprintf (outfile, " offset: %lu\n", die->die_offset);
+  fprintf (outfile, " offset: %ld\n", die->die_offset);
 
   for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
     {
@@ -5792,7 +5850,7 @@ print_die (dw_die_ref die, FILE *outfile)
              if (AT_ref (a)->die_symbol)
                fprintf (outfile, "die -> label: %s", AT_ref (a)->die_symbol);
              else
-               fprintf (outfile, "die -> %lu", AT_ref (a)->die_offset);
+               fprintf (outfile, "die -> %ld", AT_ref (a)->die_offset);
            }
          else
            fprintf (outfile, "die -> <null>");
@@ -6119,7 +6177,7 @@ same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark)
   if (VEC_length (dw_attr_node, die1->die_attr)
       != VEC_length (dw_attr_node, die2->die_attr))
     return 0;
-  
+
   for (ix = 0; VEC_iterate (dw_attr_node, die1->die_attr, ix, a1); ix++)
     if (!same_attr_p (a1, VEC_index (dw_attr_node, die2->die_attr, ix), mark))
       return 0;
@@ -6424,7 +6482,7 @@ break_out_includes (dw_die_ref die)
 
        /* This DIE is for a secondary CU; remove it from the main one.  */
        remove_child_with_prev (c, prev);
-       
+
        if (c->die_tag == DW_TAG_GNU_BINCL)
          unit = push_new_compile_unit (unit, c);
        else if (c->die_tag == DW_TAG_GNU_EINCL)
@@ -6532,16 +6590,16 @@ build_abbrev_table (dw_die_ref die)
       dw_attr_ref die_a, abbrev_a;
       unsigned ix;
       bool ok = true;
-      
+
       if (abbrev->die_tag != die->die_tag)
        continue;
       if ((abbrev->die_child != NULL) != (die->die_child != NULL))
        continue;
-      
+
       if (VEC_length (dw_attr_node, abbrev->die_attr)
          != VEC_length (dw_attr_node, die->die_attr))
        continue;
-  
+
       for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, die_a); ix++)
        {
          abbrev_a = VEC_index (dw_attr_node, abbrev->die_attr, ix);
@@ -6749,21 +6807,22 @@ unmark_all_dies (dw_die_ref die)
       unmark_all_dies (AT_ref (a));
 }
 
-/* Return the size of the .debug_pubnames table  generated for the
-   compilation unit.  */
+/* Return the size of the .debug_pubnames or .debug_pubtypes table
+   generated for the compilation unit.  */
 
 static unsigned long
-size_of_pubnames (void)
+size_of_pubnames (VEC (pubname_entry, gc) * names)
 {
   unsigned long size;
   unsigned i;
+  pubname_ref p;
 
   size = DWARF_PUBNAMES_HEADER_SIZE;
-  for (i = 0; i < pubname_table_in_use; i++)
-    {
-      pubname_ref p = &pubname_table[i];
-      size += DWARF_OFFSET_SIZE + strlen (p->name) + 1;
-    }
+  for (i = 0; VEC_iterate (pubname_entry, names, i, p); i++)
+    if (names != pubtype_table
+       || p->die->die_offset != 0
+       || !flag_eliminate_unused_debug_types)
+      size += strlen (p->name) + DWARF_OFFSET_SIZE + 1;
 
   size += DWARF_OFFSET_SIZE;
   return size;
@@ -7062,7 +7121,8 @@ output_die (dw_die_ref die)
     output_die_symbol (die);
 
   dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)",
-                              die->die_offset, dwarf_tag_name (die->die_tag));
+                              (unsigned long)die->die_offset,
+                              dwarf_tag_name (die->die_tag));
 
   for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
     {
@@ -7228,7 +7288,7 @@ output_die (dw_die_ref die)
        case dw_val_class_file:
          {
            int f = maybe_emit_file (a->dw_attr_val.v.val_file);
-           
+
            dw2_asm_output_data (constant_size (f), f, "%s (%s)", name,
                                 a->dw_attr_val.v.val_file->filename);
            break;
@@ -7244,7 +7304,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",
-                        die->die_offset);
+                        (unsigned long) die->die_offset);
 }
 
 /* Output the compilation unit that appears at the beginning of the
@@ -7257,7 +7317,7 @@ output_compilation_unit_header (void)
     dw2_asm_output_data (4, 0xffffffff,
       "Initial length escape value indicating 64-bit DWARF extension");
   dw2_asm_output_data (DWARF_OFFSET_SIZE,
-                       next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
+                      next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
                       "Length of Compilation Unit Info");
   dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number");
   dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
@@ -7330,41 +7390,71 @@ dwarf2_name (tree decl, int scope)
 static void
 add_pubname (tree decl, dw_die_ref die)
 {
-  pubname_ref p;
+  pubname_entry e;
 
   if (! TREE_PUBLIC (decl))
     return;
 
-  if (pubname_table_in_use == pubname_table_allocated)
+  e.die = die;
+  e.name = xstrdup (dwarf2_name (decl, 1));
+  VEC_safe_push (pubname_entry, gc, pubname_table, &e);
+}
+
+/* Add a new entry to .debug_pubtypes if appropriate.  */
+
+static void
+add_pubtype (tree decl, dw_die_ref die)
+{
+  pubname_entry e;
+
+  e.name = NULL;
+  if ((TREE_PUBLIC (decl)
+       || die->die_parent == comp_unit_die)
+      && (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
     {
-      pubname_table_allocated += PUBNAME_TABLE_INCREMENT;
-      pubname_table
-       = ggc_realloc (pubname_table,
-                      (pubname_table_allocated * sizeof (pubname_entry)));
-      memset (pubname_table + pubname_table_in_use, 0,
-             PUBNAME_TABLE_INCREMENT * sizeof (pubname_entry));
-    }
+      e.die = die;
+      if (TYPE_P (decl))
+       {
+         if (TYPE_NAME (decl))
+           {
+             if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE)
+               e.name = IDENTIFIER_POINTER (TYPE_NAME (decl));
+             else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
+                      && DECL_NAME (TYPE_NAME (decl)))
+               e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
+             else
+              e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
+           }
+       }
+      else
+       e.name = xstrdup (dwarf2_name (decl, 1));
 
-  p = &pubname_table[pubname_table_in_use++];
-  p->die = die;
-  p->name = xstrdup (dwarf2_name (decl, 1));
+      /* If we don't have a name for the type, there's no point in adding
+        it to the table.  */
+      if (e.name && e.name[0] != '\0')
+       VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+    }
 }
 
 /* Output the public names table used to speed up access to externally
-   visible names.  For now, only generate entries for externally
-   visible procedures.  */
+   visible names; or the public types table used to find type definitions.  */
 
 static void
-output_pubnames (void)
+output_pubnames (VEC (pubname_entry, gc) * names)
 {
   unsigned i;
-  unsigned long pubnames_length = size_of_pubnames ();
+  unsigned long pubnames_length = size_of_pubnames (names);
+  pubname_ref pub;
 
   if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
     dw2_asm_output_data (4, 0xffffffff,
       "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
-                      "Length of Public Names Info");
+  if (names == pubname_table)
+    dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+                        "Length of Public Names Info");
+  else
+    dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+                        "Length of Public Type Names Info");
   dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version");
   dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
                         debug_info_section,
@@ -7372,17 +7462,21 @@ output_pubnames (void)
   dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
                       "Compilation Unit Length");
 
-  for (i = 0; i < pubname_table_in_use; i++)
+  for (i = 0; VEC_iterate (pubname_entry, names, i, pub); i++)
     {
-      pubname_ref pub = &pubname_table[i];
-
       /* We shouldn't see pubnames for DIEs outside of the main CU.  */
-      gcc_assert (pub->die->die_mark);
+      if (names == pubname_table)
+       gcc_assert (pub->die->die_mark);
 
-      dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
-                          "DIE offset");
+      if (names != pubtype_table
+         || pub->die->die_offset != 0
+         || !flag_eliminate_unused_debug_types)
+       {
+         dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
+                              "DIE offset");
 
-      dw2_asm_output_nstring (pub->name, -1, "external name");
+         dw2_asm_output_nstring (pub->name, -1, "external name");
+       }
     }
 
   dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
@@ -7447,7 +7541,7 @@ output_aranges (void)
                        text_section_label, "Length");
   if (flag_reorder_blocks_and_partition)
     {
-      dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label, 
+      dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label,
                           "Address");
       dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label,
                            cold_text_section_label, "Length");
@@ -7497,7 +7591,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;
 
@@ -7511,12 +7605,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 (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)
 {
@@ -7526,9 +7656,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];
@@ -7548,10 +7678,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,
@@ -7561,6 +7691,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);
@@ -7629,7 +7791,7 @@ file_info_cmp (const void *p1, const void *p2)
     }
 }
 
-struct file_name_acquire_data 
+struct file_name_acquire_data
 {
   struct file_info *files;
   int used_files;
@@ -7659,17 +7821,17 @@ file_name_acquire (void ** slot, void *data)
   f = d->filename;
   while (f[0] == '.' && IS_DIR_SEPARATOR (f[1]))
     f += 2;
-  
+
   /* Create a new array entry.  */
   fi->path = f;
   fi->length = strlen (f);
   fi->file_idx = d;
-  
+
   /* Search for the file name part.  */
   f = strrchr (f, DIR_SEPARATOR);
 #if defined (DIR_SEPARATOR_2)
   {
-    char *g = strrchr (files[i].path, DIR_SEPARATOR_2);
+    char *g = strrchr (fi->path, DIR_SEPARATOR_2);
 
     if (g != NULL)
       {
@@ -8249,35 +8411,6 @@ base_type_die (tree type)
   return base_type_result;
 }
 
-/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to
-   the Dwarf "root" type for the given input type.  The Dwarf "root" type of
-   a given type is generally the same as the given type, except that if the
-   given type is a pointer or reference type, then the root type of the given
-   type is the root type of the "basis" type for the pointer or reference
-   type.  (This definition of the "root" type is recursive.) Also, the root
-   type of a `const' qualified type or a `volatile' qualified type is the
-   root type of the given type without the qualifiers.  */
-
-static tree
-root_type (tree type)
-{
-  if (TREE_CODE (type) == ERROR_MARK)
-    return error_mark_node;
-
-  switch (TREE_CODE (type))
-    {
-    case ERROR_MARK:
-      return error_mark_node;
-
-    case POINTER_TYPE:
-    case REFERENCE_TYPE:
-      return type_main_variant (root_type (TREE_TYPE (type)));
-
-    default:
-      return type_main_variant (type);
-    }
-}
-
 /* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
    given input type is a Dwarf "fundamental" type.  Otherwise return null.  */
 
@@ -8364,26 +8497,26 @@ is_subrange_type (tree type)
       && tree_int_cst_equal (TYPE_MAX_VALUE (type), TYPE_MAX_VALUE (subtype)))
     {
       /* The type and its subtype have the same representation.  If in
-         addition the two types also have the same name, then the given
-         type is not a subrange type, but rather a plain base type.  */
+        addition the two types also have the same name, then the given
+        type is not a subrange type, but rather a plain base type.  */
       /* FIXME: brobecker/2004-03-22:
-         Sizetype INTEGER_CSTs nodes are canonicalized.  It should
-         therefore be sufficient to check the TYPE_SIZE node pointers
-         rather than checking the actual size.  Unfortunately, we have
-         found some cases, such as in the Ada "integer" type, where
-         this is not the case.  Until this problem is solved, we need to
-         keep checking the actual size.  */
+        Sizetype INTEGER_CSTs nodes are canonicalized.  It should
+        therefore be sufficient to check the TYPE_SIZE node pointers
+        rather than checking the actual size.  Unfortunately, we have
+        found some cases, such as in the Ada "integer" type, where
+        this is not the case.  Until this problem is solved, we need to
+        keep checking the actual size.  */
       tree type_name = TYPE_NAME (type);
       tree subtype_name = TYPE_NAME (subtype);
 
       if (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
-        type_name = DECL_NAME (type_name);
+       type_name = DECL_NAME (type_name);
 
       if (subtype_name != NULL && TREE_CODE (subtype_name) == TYPE_DECL)
-        subtype_name = DECL_NAME (subtype_name);
+       subtype_name = DECL_NAME (subtype_name);
 
       if (type_name == subtype_name)
-        return false;
+       return false;
     }
 
   return true;
@@ -8406,16 +8539,16 @@ subrange_type_die (tree type, dw_die_ref context_die)
   if (int_size_in_bytes (TREE_TYPE (type)) != size_in_bytes)
     {
       /* The size of the subrange type and its base type do not match,
-         so we need to generate a size attribute for the subrange type.  */
+        so we need to generate a size attribute for the subrange type.  */
       add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes);
     }
 
   if (TYPE_MIN_VALUE (type) != NULL)
     add_bound_info (subrange_die, DW_AT_lower_bound,
-                    TYPE_MIN_VALUE (type));
+                   TYPE_MIN_VALUE (type));
   if (TYPE_MAX_VALUE (type) != NULL)
     add_bound_info (subrange_die, DW_AT_upper_bound,
-                    TYPE_MAX_VALUE (type));
+                   TYPE_MAX_VALUE (type));
 
   return subrange_die;
 }
@@ -8443,7 +8576,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
     = get_qualified_type (type,
                          ((is_const_type ? TYPE_QUAL_CONST : 0)
                           | (is_volatile_type ? TYPE_QUAL_VOLATILE : 0)));
-  
+
   /* If we do, then we can just use its DIE, if it exists.  */
   if (qualified_type)
     {
@@ -8451,23 +8584,25 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
       if (mod_type_die)
        return mod_type_die;
     }
-  
+
   name = qualified_type ? TYPE_NAME (qualified_type) : NULL;
-  
+
   /* Handle C typedef types.  */
   if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name))
     {
       tree dtype = TREE_TYPE (name);
-      
+
       if (qualified_type == dtype)
        {
          /* For a named type, use the typedef.  */
          gen_type_die (qualified_type, context_die);
          return lookup_type_die (qualified_type);
        }
-      else if (DECL_ORIGINAL_TYPE (name)
-              && (is_const_type < TYPE_READONLY (dtype)
-                  || is_volatile_type < TYPE_VOLATILE (dtype)))
+      else if (is_const_type < TYPE_READONLY (dtype)
+              || is_volatile_type < TYPE_VOLATILE (dtype)
+              || (is_const_type <= TYPE_READONLY (dtype)
+                  && is_volatile_type <= TYPE_VOLATILE (dtype)
+                  && DECL_ORIGINAL_TYPE (name) != type))
        /* cv-unqualified version of named type.  Just use the unnamed
           type to which it refers.  */
        return modified_type_die (DECL_ORIGINAL_TYPE (name),
@@ -8475,7 +8610,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
                                  context_die);
       /* Else cv-qualified version of named type; fall through.  */
     }
-  
+
   if (is_const_type)
     {
       mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type);
@@ -8510,7 +8645,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
   else
     {
       gen_type_die (type, context_die);
-      
+
       /* We have to get the type_main_variant here (and pass that to the
         `lookup_type_die' routine) because the ..._TYPE node we have
         might simply be a *copy* of some original type node (where the
@@ -8524,7 +8659,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
           not the main variant.  */
        return lookup_type_die (type);
     }
-  
+
   /* Builtin types don't have a DECL_ORIGINAL_TYPE.  For those,
      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.  */
@@ -8538,7 +8673,7 @@ 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));
     }
-  
+
   if (qualified_type)
     equate_type_number_to_die (qualified_type, mod_type_die);
 
@@ -8577,13 +8712,12 @@ dbx_reg_number (rtx rtl)
   gcc_assert (regno < FIRST_PSEUDO_REGISTER);
 
 #ifdef LEAF_REG_REMAP
-  {
-    int leaf_reg;
-
-    leaf_reg = LEAF_REG_REMAP (regno);
-    if (leaf_reg != -1)
-      regno = (unsigned) leaf_reg;
-  }
+  if (current_function_uses_only_leaf_regs)
+    {
+      int leaf_reg = LEAF_REG_REMAP (regno);
+      if (leaf_reg != -1)
+       regno = (unsigned) leaf_reg;
+    }
 #endif
 
   return DBX_REGISTER_NUMBER (regno);
@@ -8652,13 +8786,12 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
 
   reg = REGNO (rtl);
 #ifdef LEAF_REG_REMAP
-  {
-    int leaf_reg;
-
-    leaf_reg = LEAF_REG_REMAP (reg);
-    if (leaf_reg != -1)
-      reg = (unsigned) leaf_reg;
-  }
+  if (current_function_uses_only_leaf_regs)
+    {
+      int leaf_reg = LEAF_REG_REMAP (reg);
+      if (leaf_reg != -1)
+       reg = (unsigned) leaf_reg;
+    }
 #endif
   gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
   nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
@@ -8763,9 +8896,9 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset)
            }
          gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
                      : stack_pointer_rtx));
-          offset += frame_pointer_fb_offset;
+         offset += frame_pointer_fb_offset;
 
-          return new_loc_descr (DW_OP_fbreg, offset, 0);
+         return new_loc_descr (DW_OP_fbreg, offset, 0);
        }
     }
 
@@ -8787,6 +8920,32 @@ is_based_loc (rtx rtl)
               && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
 }
 
+/* Return a descriptor that describes the concatenation of N locations
+   used to form the address of a memory location.  */
+
+static dw_loc_descr_ref
+concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
+{
+  unsigned int i;
+  dw_loc_descr_ref cc_loc_result = NULL;
+  unsigned int n = XVECLEN (concatn, 0);
+
+  for (i = 0; i < n; ++i)
+    {
+      dw_loc_descr_ref ref;
+      rtx x = XVECEXP (concatn, 0, i);
+
+      ref = mem_loc_descriptor (x, mode);
+      if (ref == NULL)
+       return NULL;
+
+      add_loc_descr (&cc_loc_result, ref);
+      add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
+    }
+
+  return cc_loc_result;
+}
+
 /* The following routine converts the RTL for a variable or parameter
    (resident in memory) into an equivalent Dwarf representation of a
    mechanism for getting the address of that same variable onto the top of a
@@ -8982,6 +9141,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
       mem_loc_result = int_loc_descriptor (INTVAL (rtl));
       break;
 
+    case CONCATN:
+      mem_loc_result = concatn_mem_loc_descriptor (rtl, mode);
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -9011,6 +9174,32 @@ concat_loc_descriptor (rtx x0, rtx x1)
   return cc_loc_result;
 }
 
+/* Return a descriptor that describes the concatenation of N
+   locations.  */
+
+static dw_loc_descr_ref
+concatn_loc_descriptor (rtx concatn)
+{
+  unsigned int i;
+  dw_loc_descr_ref cc_loc_result = NULL;
+  unsigned int n = XVECLEN (concatn, 0);
+
+  for (i = 0; i < n; ++i)
+    {
+      dw_loc_descr_ref ref;
+      rtx x = XVECEXP (concatn, 0, i);
+
+      ref = loc_descriptor (x);
+      if (ref == NULL)
+       return NULL;
+
+      add_loc_descr (&cc_loc_result, ref);
+      add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
+    }
+
+  return cc_loc_result;
+}
+
 /* Output a proper Dwarf location descriptor for a variable or parameter
    which is either allocated in a register or in a memory location.  For a
    register, we just generate an OP_REG and the register number.  For a
@@ -9048,6 +9237,10 @@ loc_descriptor (rtx rtl)
       loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
       break;
 
+    case CONCATN:
+      loc_result = concatn_loc_descriptor (rtl);
+      break;
+
     case VAR_LOCATION:
       /* Single part.  */
       if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
@@ -9142,7 +9335,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
          rtx rtl;
 
          /* If this is not defined, we have no way to emit the data.  */
-         if (!targetm.asm_out.output_dwarf_dtprel)
+         if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel)
            return 0;
 
          /* The way DW_OP_GNU_push_tls_address is specified, we can only
@@ -9185,7 +9378,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
 
        if (rtl == NULL_RTX)
          return 0;
-        else if (GET_CODE (rtl) == CONST_INT)
+       else if (GET_CODE (rtl) == CONST_INT)
          {
            HOST_WIDE_INT val = INTVAL (rtl);
            if (TYPE_UNSIGNED (TREE_TYPE (loc)))
@@ -9232,8 +9425,9 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
     case NON_LVALUE_EXPR:
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
-    case MODIFY_EXPR:
-      return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
+    case GIMPLE_MODIFY_STMT:
+      return loc_descriptor_from_tree_1 (GENERIC_TREE_OPERAND (loc, 0),
+                                        want_address);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -9346,6 +9540,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
       op = (TYPE_UNSIGNED (TREE_TYPE (loc)) ? DW_OP_shr : DW_OP_shra);
       goto do_binop;
 
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
          && host_integerp (TREE_OPERAND (loc, 1), 0))
@@ -9435,13 +9630,13 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
     case MIN_EXPR:
     case MAX_EXPR:
       {
-        const enum tree_code code =
-          TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
+       const enum tree_code code =
+         TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
 
-        loc = build3 (COND_EXPR, TREE_TYPE (loc),
+       loc = build3 (COND_EXPR, TREE_TYPE (loc),
                      build2 (code, integer_type_node,
                              TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
-                      TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+                     TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
       }
 
       /* ... fall through ...  */
@@ -9478,16 +9673,13 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
       break;
 
     case FIX_TRUNC_EXPR:
-    case FIX_CEIL_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
       return 0;
 
     default:
       /* Leave front-end specific codes as simply unknown.  This comes
         up, for instance, with the C STMT_EXPR.  */
       if ((unsigned int) TREE_CODE (loc)
-          >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
+         >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
        return 0;
 
 #ifdef ENABLE_CHECKING
@@ -9574,6 +9766,24 @@ simple_decl_align_in_bits (tree decl)
   return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
 }
 
+/* Return the result of rounding T up to ALIGN.  */
+
+static inline HOST_WIDE_INT
+round_up_to_align (HOST_WIDE_INT t, unsigned int align)
+{
+  /* We must be careful if T is negative because HOST_WIDE_INT can be
+     either "above" or "below" unsigned int as per the C promotion
+     rules, depending on the host, thus making the signedness of the
+     direct multiplication and division unpredictable.  */
+  unsigned HOST_WIDE_INT u = (unsigned HOST_WIDE_INT) t;
+
+  u += align - 1;
+  u /= align;
+  u *= align;
+
+  return (HOST_WIDE_INT) u;
+}
+
 /* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
    lowest addressed byte of the "containing object" for the given FIELD_DECL,
    or return 0 if we are unable to determine what that offset is, either
@@ -9584,29 +9794,14 @@ simple_decl_align_in_bits (tree decl)
 static HOST_WIDE_INT
 field_byte_offset (tree decl)
 {
-  unsigned int type_align_in_bits;
-  unsigned int decl_align_in_bits;
-  unsigned HOST_WIDE_INT type_size_in_bits;
   HOST_WIDE_INT object_offset_in_bits;
-  tree type;
-  tree field_size_tree;
   HOST_WIDE_INT bitpos_int;
-  HOST_WIDE_INT deepest_bitpos;
-  unsigned HOST_WIDE_INT field_size_in_bits;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return 0;
 
   gcc_assert (TREE_CODE (decl) == FIELD_DECL);
 
-  type = field_type (decl);
-  field_size_tree = DECL_SIZE (decl);
-
-  /* The size could be unspecified if there was an error, or for
-     a flexible array member.  */
-  if (! field_size_tree)
-    field_size_tree = bitsize_zero_node;
-
   /* We cannot yet cope with fields whose positions are variable, so
      for now, when we see such things, we simply return 0.  Someday, we may
      be able to handle such cases, but it will be damn difficult.  */
@@ -9615,78 +9810,105 @@ field_byte_offset (tree decl)
 
   bitpos_int = int_bit_position (decl);
 
-  /* If we don't know the size of the field, pretend it's a full word.  */
-  if (host_integerp (field_size_tree, 1))
-    field_size_in_bits = tree_low_cst (field_size_tree, 1);
-  else
-    field_size_in_bits = BITS_PER_WORD;
-
-  type_size_in_bits = simple_type_size_in_bits (type);
-  type_align_in_bits = simple_type_align_in_bits (type);
-  decl_align_in_bits = simple_decl_align_in_bits (decl);
-
-  /* The GCC front-end doesn't make any attempt to keep track of the starting
-     bit offset (relative to the start of the containing structure type) of the
-     hypothetical "containing object" for a bit-field.  Thus, when computing
-     the byte offset value for the start of the "containing object" of a
-     bit-field, we must deduce this information on our own. This can be rather
-     tricky to do in some cases.  For example, handling the following structure
-     type definition when compiling for an i386/i486 target (which only aligns
-     long long's to 32-bit boundaries) can be very tricky:
+#ifdef PCC_BITFIELD_TYPE_MATTERS
+  if (PCC_BITFIELD_TYPE_MATTERS)
+    {
+      tree type;
+      tree field_size_tree;
+      HOST_WIDE_INT deepest_bitpos;
+      unsigned HOST_WIDE_INT field_size_in_bits;
+      unsigned int type_align_in_bits;
+      unsigned int decl_align_in_bits;
+      unsigned HOST_WIDE_INT type_size_in_bits;
+
+      type = field_type (decl);
+      field_size_tree = DECL_SIZE (decl);
+
+      /* The size could be unspecified if there was an error, or for
+         a flexible array member.  */
+      if (! field_size_tree)
+        field_size_tree = bitsize_zero_node;
+
+      /* If we don't know the size of the field, pretend it's a full word.  */
+      if (host_integerp (field_size_tree, 1))
+        field_size_in_bits = tree_low_cst (field_size_tree, 1);
+      else
+        field_size_in_bits = BITS_PER_WORD;
+
+      type_size_in_bits = simple_type_size_in_bits (type);
+      type_align_in_bits = simple_type_align_in_bits (type);
+      decl_align_in_bits = simple_decl_align_in_bits (decl);
+
+      /* The GCC front-end doesn't make any attempt to keep track of the
+         starting bit offset (relative to the start of the containing
+         structure type) of the hypothetical "containing object" for a
+         bit-field.  Thus, when computing the byte offset value for the
+         start of the "containing object" of a bit-field, we must deduce
+         this information on our own. This can be rather tricky to do in
+         some cases.  For example, handling the following structure type
+         definition when compiling for an i386/i486 target (which only
+         aligns long long's to 32-bit boundaries) can be very tricky:
 
         struct S { int field1; long long field2:31; };
 
-     Fortunately, there is a simple rule-of-thumb which can be used in such
-     cases.  When compiling for an i386/i486, GCC will allocate 8 bytes for the
-     structure shown above.  It decides to do this based upon one simple rule
-     for bit-field allocation.  GCC allocates each "containing object" for each
-     bit-field at the first (i.e. lowest addressed) legitimate alignment
-     boundary (based upon the required minimum alignment for the declared type
-     of the field) which it can possibly use, subject to the condition that
-     there is still enough available space remaining in the containing object
-     (when allocated at the selected point) to fully accommodate all of the
-     bits of the bit-field itself.
-
-     This simple rule makes it obvious why GCC allocates 8 bytes for each
-     object of the structure type shown above.  When looking for a place to
-     allocate the "containing object" for `field2', the compiler simply tries
-     to allocate a 64-bit "containing object" at each successive 32-bit
-     boundary (starting at zero) until it finds a place to allocate that 64-
-     bit field such that at least 31 contiguous (and previously unallocated)
-     bits remain within that selected 64 bit field.  (As it turns out, for the
-     example above, the compiler finds it is OK to allocate the "containing
-     object" 64-bit field at bit-offset zero within the structure type.)
-
-     Here we attempt to work backwards from the limited set of facts we're
-     given, and we try to deduce from those facts, where GCC must have believed
-     that the containing object started (within the structure type). The value
-     we deduce is then used (by the callers of this routine) to generate
-     DW_AT_location and DW_AT_bit_offset attributes for fields (both bit-fields
-     and, in the case of DW_AT_location, regular fields as well).  */
-
-  /* Figure out the bit-distance from the start of the structure to the
-     "deepest" bit of the bit-field.  */
-  deepest_bitpos = bitpos_int + field_size_in_bits;
-
-  /* This is the tricky part.  Use some fancy footwork to deduce where the
-     lowest addressed bit of the containing object must be.  */
-  object_offset_in_bits = deepest_bitpos - type_size_in_bits;
-
-  /* Round up to type_align by default.  This works best for bitfields.  */
-  object_offset_in_bits += type_align_in_bits - 1;
-  object_offset_in_bits /= type_align_in_bits;
-  object_offset_in_bits *= type_align_in_bits;
-
-  if (object_offset_in_bits > bitpos_int)
-    {
-      /* Sigh, the decl must be packed.  */
+         Fortunately, there is a simple rule-of-thumb which can be used
+         in such cases.  When compiling for an i386/i486, GCC will
+         allocate 8 bytes for the structure shown above.  It decides to
+         do this based upon one simple rule for bit-field allocation.
+         GCC allocates each "containing object" for each bit-field at
+         the first (i.e. lowest addressed) legitimate alignment boundary
+         (based upon the required minimum alignment for the declared
+         type of the field) which it can possibly use, subject to the
+         condition that there is still enough available space remaining
+         in the containing object (when allocated at the selected point)
+         to fully accommodate all of the bits of the bit-field itself.
+
+         This simple rule makes it obvious why GCC allocates 8 bytes for
+         each object of the structure type shown above.  When looking
+         for a place to allocate the "containing object" for `field2',
+         the compiler simply tries to allocate a 64-bit "containing
+         object" at each successive 32-bit boundary (starting at zero)
+         until it finds a place to allocate that 64- bit field such that
+         at least 31 contiguous (and previously unallocated) bits remain
+         within that selected 64 bit field.  (As it turns out, for the
+         example above, the compiler finds it is OK to allocate the
+         "containing object" 64-bit field at bit-offset zero within the
+         structure type.)
+
+         Here we attempt to work backwards from the limited set of facts
+         we're given, and we try to deduce from those facts, where GCC
+         must have believed that the containing object started (within
+         the structure type). The value we deduce is then used (by the
+         callers of this routine) to generate DW_AT_location and
+         DW_AT_bit_offset attributes for fields (both bit-fields and, in
+         the case of DW_AT_location, regular fields as well).  */
+
+      /* Figure out the bit-distance from the start of the structure to
+         the "deepest" bit of the bit-field.  */
+      deepest_bitpos = bitpos_int + field_size_in_bits;
+
+      /* This is the tricky part.  Use some fancy footwork to deduce
+         where the lowest addressed bit of the containing object must
+         be.  */
       object_offset_in_bits = deepest_bitpos - type_size_in_bits;
 
-      /* Round up to decl_align instead.  */
-      object_offset_in_bits += decl_align_in_bits - 1;
-      object_offset_in_bits /= decl_align_in_bits;
-      object_offset_in_bits *= decl_align_in_bits;
+      /* Round up to type_align by default.  This works best for
+         bitfields.  */
+      object_offset_in_bits
+        = round_up_to_align (object_offset_in_bits, type_align_in_bits);
+
+      if (object_offset_in_bits > bitpos_int)
+        {
+          object_offset_in_bits = deepest_bitpos - type_size_in_bits;
+
+          /* Round up to decl_align instead.  */
+          object_offset_in_bits
+            = round_up_to_align (object_offset_in_bits, decl_align_in_bits);
+        }
     }
+  else
+#endif
+    object_offset_in_bits = bitpos_int;
 
   return object_offset_in_bits / BITS_PER_UNIT;
 }
@@ -10009,14 +10231,32 @@ static tree
 reference_to_unused (tree * tp, int * walk_subtrees,
                     void * data ATTRIBUTE_UNUSED)
 {
-  if (! EXPR_P (*tp) && ! CONSTANT_CLASS_P (*tp))
+  if (! EXPR_P (*tp) && ! GIMPLE_STMT_P (*tp) && ! CONSTANT_CLASS_P (*tp))
     *walk_subtrees = 0;
-  
+
   if (DECL_P (*tp) && ! TREE_PUBLIC (*tp) && ! TREE_USED (*tp)
       && ! TREE_ASM_WRITTEN (*tp))
     return *tp;
-  else
+  else if (!flag_unit_at_a_time)
     return NULL_TREE;
+  else if (!cgraph_global_info_ready
+          && (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
+    gcc_unreachable ();
+  else if (DECL_P (*tp) && TREE_CODE (*tp) == VAR_DECL)
+    {
+      struct varpool_node *node = varpool_node (*tp);
+      if (!node->needed)
+       return *tp;
+    }
+  else if (DECL_P (*tp) && TREE_CODE (*tp) == FUNCTION_DECL
+          && (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp)))
+    {
+      struct cgraph_node *node = cgraph_node (*tp);
+      if (!node->output)
+       return *tp;
+    }
+
+  return NULL_TREE;
 }
 
 /* Generate an RTL constant from a decl initializer INIT with decl type TYPE,
@@ -10049,7 +10289,7 @@ rtl_for_decl_init (tree init, tree type)
      CONCAT: FIXME!  */
   else if (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
     ;
-  /* Vectors only work if their mode is supported by the target.  
+  /* Vectors only work if their mode is supported by the target.
      FIXME: generic vectors ought to work too.  */
   else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_MODE (type) == BLKmode)
     ;
@@ -10324,7 +10564,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
 
   gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
              || TREE_CODE (decl) == RESULT_DECL);
-            
+
   /* See if we possibly have multiple locations for this variable.  */
   loc_list = lookup_decl_loc (decl);
 
@@ -10337,7 +10577,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
       rtx varloc;
 
       /* Now that we know what section we are using for a base,
-         actually construct the list of locations.
+        actually construct the list of locations.
         The first location information is what is passed to the
         function that creates the location list, and the remaining
         locations just get added on to that list.
@@ -10391,14 +10631,14 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
 
   /* Try to get some constant RTL for this decl, and use that as the value of
      the location.  */
-  
+
   rtl = rtl_for_decl_location (decl);
   if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
     {
       add_const_value_attribute (die, rtl);
       return;
     }
-  
+
   /* If we have tried to generate the location otherwise, and it
      didn't work out (we wouldn't be here if we did), and we have a one entry
      location list, try generating a location from that.  */
@@ -10880,7 +11120,7 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
 
       if (TYPE_P (fn))
        fn = TYPE_STUB_DECL (fn);
-      
+
       fn = decl_function_context (fn);
       if (fn)
        dwarf2out_abstract_function (fn);
@@ -11147,10 +11387,17 @@ type_tag (tree type)
         involved.  */
       else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
               && ! DECL_IGNORED_P (TYPE_NAME (type)))
-       t = DECL_NAME (TYPE_NAME (type));
+       {
+         /* We want to be extra verbose.  Don't call dwarf_name if
+            DECL_NAME isn't set.  The default hook for decl_printable_name
+            doesn't like that, and in this context it's correct to return
+            0, instead of "<anonymous>" or the like.  */
+         if (DECL_NAME (TYPE_NAME (type)))
+           name = lang_hooks.dwarf_name (TYPE_NAME (type), 2);
+       }
 
       /* Now get the name as a string, or invent one.  */
-      if (t != 0)
+      if (!name && t != 0)
        name = IDENTIFIER_POINTER (t);
     }
 
@@ -11253,6 +11500,9 @@ gen_array_type_die (tree type, dw_die_ref context_die)
 #endif
 
   add_type_attribute (array_die, element_type, 0, 0, context_die);
+
+  if (get_AT (array_die, DW_AT_name))
+    add_pubtype (type, array_die);
 }
 
 #if 0
@@ -11388,6 +11638,9 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
   else
     add_AT_flag (type_die, DW_AT_declaration, 1);
 
+  if (get_AT (type_die, DW_AT_name))
+    add_pubtype (type, type_die);
+
   return type_die;
 }
 
@@ -11770,7 +12023,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
     {
       if (DECL_DECLARED_INLINE_P (decl))
        {
-          if (cgraph_function_possibly_inlined_p (decl))
+         if (cgraph_function_possibly_inlined_p (decl))
            add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined);
          else
            add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined);
@@ -11778,9 +12031,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       else
        {
          if (cgraph_function_possibly_inlined_p (decl))
-            add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined);
+           add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined);
          else
-            add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined);
+           add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined);
        }
 
       equate_decl_number_to_die (decl, subr_die);
@@ -11800,7 +12053,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
                                       current_function_funcdef_no);
          add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
-         
+
          add_pubname (decl, subr_die);
          add_arange (decl, subr_die);
        }
@@ -11849,7 +12102,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
       /* Compute a displacement from the "steady-state frame pointer" to
         the CFA.  The former is what all stack slots and argument slots
-        will reference in the rtl; the later is what we've told the 
+        will reference in the rtl; the later is what we've told the
         debugger about.  We'll need to adjust all frame_base references
         by this displacement.  */
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
@@ -11972,17 +12225,17 @@ gen_variable_die (tree decl, dw_die_ref context_die)
                        the program.  For example, consider the C++
                        test case:
 
-                          template <class T>
-                          struct S { static const int i = 7; };
+                         template <class T>
+                         struct S { static const int i = 7; };
 
-                          template <class T>
-                          const int S<T>::i;
+                         template <class T>
+                         const int S<T>::i;
+
+                         int f() { return S<int>::i; }
 
-                          int f() { return S<int>::i; }
-                         
                        Here, S<int>::i is not DECL_EXTERNAL, but no
                        definition is required, so the compiler will
-                       not emit a definition.  */  
+                       not emit a definition.  */
                     || (TREE_CODE (decl) == VAR_DECL
                         && DECL_COMDAT (decl) && !TREE_ASM_WRITTEN (decl))
                     || class_or_namespace_scope_p (context_die));
@@ -12017,7 +12270,6 @@ gen_variable_die (tree decl, dw_die_ref context_die)
            add_AT_file (var_die, DW_AT_decl_file, file_index);
 
          if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
-
            add_AT_unsigned (var_die, DW_AT_decl_line, s.line);
        }
     }
@@ -12081,7 +12333,7 @@ gen_label_die (tree decl, dw_die_ref context_die)
       if (insn
          && (LABEL_P (insn)
              || ((NOTE_P (insn)
-                  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))))
+                  && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))))
        {
          /* When optimization is enabled (via -O) some parts of the compiler
             (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which
@@ -12109,6 +12361,36 @@ add_call_src_coords_attributes (tree stmt, dw_die_ref die)
   add_AT_unsigned (die, DW_AT_call_line, s.line);
 }
 
+
+/* If STMT's abstract origin is a function declaration and STMT's
+   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)
+{
+  tree decl, block;
+
+  if (!stmt || TREE_CODE (stmt) != BLOCK)
+    return false;
+
+  decl = block_ultimate_origin (stmt);
+
+  if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
+    return false;
+
+  block = BLOCK_SUBBLOCKS (stmt);
+
+  if (block)
+    {
+      if (TREE_CODE (block) != BLOCK)
+       return false;
+
+      block = block_ultimate_origin (block);
+    }
+
+  return block == DECL_INITIAL (decl);
+}
+
 /* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
    Add low_pc and high_pc attributes to the DIE for a block STMT.  */
 
@@ -12121,6 +12403,13 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
     {
       tree chain;
 
+      if (is_inlined_entry_point (stmt))
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
+                                      BLOCK_NUMBER (stmt));
+         add_AT_lbl_id (die, DW_AT_entry_pc, label);
+       }
+
       add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
 
       chain = BLOCK_FRAGMENT_CHAIN (stmt);
@@ -12430,7 +12719,8 @@ gen_member_die (tree type, dw_die_ref context_die)
    member DIEs needed by later specification DIEs.  */
 
 static void
-gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
+gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
+                               enum debug_info_usage usage)
 {
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref scope_die = 0;
@@ -12439,6 +12729,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
                  && (! TYPE_STUB_DECL (type)
                      || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))));
   int ns_decl = (context_die && context_die->die_tag == DW_TAG_namespace);
+  complete = complete && should_emit_struct_debug (type, usage);
 
   if (type_die && ! complete)
     return;
@@ -12506,6 +12797,9 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
          && ! decl_function_context (TYPE_STUB_DECL (type)))
        VEC_safe_push (tree, gc, incomplete_types, type);
     }
+
+  if (get_AT (type_die, DW_AT_name))
+    add_pubtype (type, type_die);
 }
 
 /* Generate a DIE for a subroutine _type_.  */
@@ -12522,6 +12816,9 @@ gen_subroutine_type_die (tree type, dw_die_ref context_die)
   add_prototyped_attribute (subr_die, type);
   add_type_attribute (subr_die, return_type, 0, 0, context_die);
   gen_formal_types_die (type, subr_die);
+
+  if (get_AT (subr_die, DW_AT_name))
+    add_pubtype (type, subr_die);
 }
 
 /* Generate a DIE for a type definition.  */
@@ -12561,12 +12858,16 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
 
   if (DECL_ABSTRACT (decl))
     equate_decl_number_to_die (decl, type_die);
+
+  if (get_AT (type_die, DW_AT_name))
+    add_pubtype (decl, type_die);
 }
 
 /* Generate a type description DIE.  */
 
 static void
-gen_type_die (tree type, dw_die_ref context_die)
+gen_type_die_with_usage (tree type, dw_die_ref context_die,
+                               enum debug_info_usage usage)
 {
   int need_pop;
 
@@ -12614,16 +12915,19 @@ gen_type_die (tree type, dw_die_ref context_die)
 
       /* For these types, all that is required is that we output a DIE (or a
         set of DIEs) to represent the "basis" type.  */
-      gen_type_die (TREE_TYPE (type), context_die);
+      gen_type_die_with_usage (TREE_TYPE (type), context_die,
+                               DINFO_USAGE_IND_USE);
       break;
 
     case OFFSET_TYPE:
       /* This code is used for C++ pointer-to-data-member types.
         Output a description of the relevant class type.  */
-      gen_type_die (TYPE_OFFSET_BASETYPE (type), context_die);
+      gen_type_die_with_usage (TYPE_OFFSET_BASETYPE (type), context_die,
+                                       DINFO_USAGE_IND_USE);
 
       /* Output a description of the type of the object pointed to.  */
-      gen_type_die (TREE_TYPE (type), context_die);
+      gen_type_die_with_usage (TREE_TYPE (type), context_die,
+                                       DINFO_USAGE_IND_USE);
 
       /* Now output a DIE to represent this pointer-to-data-member type
         itself.  */
@@ -12632,13 +12936,15 @@ gen_type_die (tree type, dw_die_ref context_die)
 
     case FUNCTION_TYPE:
       /* Force out return type (in case it wasn't forced out already).  */
-      gen_type_die (TREE_TYPE (type), context_die);
+      gen_type_die_with_usage (TREE_TYPE (type), context_die,
+                                       DINFO_USAGE_DIR_USE);
       gen_subroutine_type_die (type, context_die);
       break;
 
     case METHOD_TYPE:
       /* Force out return type (in case it wasn't forced out already).  */
-      gen_type_die (TREE_TYPE (type), context_die);
+      gen_type_die_with_usage (TREE_TYPE (type), context_die,
+                                       DINFO_USAGE_DIR_USE);
       gen_subroutine_type_die (type, context_die);
       break;
 
@@ -12664,7 +12970,7 @@ gen_type_die (tree type, dw_die_ref context_die)
          && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
          && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
        {
-         gen_type_die (TYPE_CONTEXT (type), context_die);
+         gen_type_die_with_usage (TYPE_CONTEXT (type), context_die, usage);
 
          if (TREE_ASM_WRITTEN (type))
            return;
@@ -12681,9 +12987,14 @@ gen_type_die (tree type, dw_die_ref context_die)
        }
 
       if (TREE_CODE (type) == ENUMERAL_TYPE)
-       gen_enumeration_type_die (type, context_die);
+       {
+         /* This might have been written out by the call to
+            declare_in_namespace.  */
+         if (!TREE_ASM_WRITTEN (type))
+           gen_enumeration_type_die (type, context_die);
+       }
       else
-       gen_struct_or_union_type_die (type, context_die);
+       gen_struct_or_union_type_die (type, context_die, usage);
 
       if (need_pop)
        pop_decl_scope ();
@@ -12712,6 +13023,12 @@ gen_type_die (tree type, dw_die_ref context_die)
   TREE_ASM_WRITTEN (type) = 1;
 }
 
+static void
+gen_type_die (tree type, dw_die_ref context_die)
+{
+  gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+}
+
 /* Generate a DIE for a tagged type instantiation.  */
 
 static void
@@ -12810,8 +13127,8 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
          if (debug_info_level > DINFO_LEVEL_TERSE)
            /* We are not in terse mode so *any* local declaration counts
               as being a "significant" one.  */
-           must_output_die = (BLOCK_VARS (stmt) != NULL 
-                              && (TREE_USED (stmt) 
+           must_output_die = (BLOCK_VARS (stmt) != NULL
+                              && (TREE_USED (stmt)
                                   || TREE_ASM_WRITTEN (stmt)
                                   || BLOCK_ABSTRACT (stmt)));
          else
@@ -12868,19 +13185,19 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
       for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
        {
          dw_die_ref die;
-         
+
          if (TREE_CODE (decl) == FUNCTION_DECL)
            die = lookup_decl_die (decl);
          else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
            die = lookup_type_die (TREE_TYPE (decl));
          else
            die = NULL;
-         
+
          if (die != NULL && die->die_parent == NULL)
            add_child_die (context_die, die);
          /* Do not produce debug information for static variables since
             these might be optimized out.  We are called for these later
-            in cgraph_varpool_analyze_pending_decls. */
+            in varpool_analyze_pending_decls. */
          if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
            ;
          else
@@ -12985,7 +13302,8 @@ force_decl_die (tree decl)
   return decl_die;
 }
 
-/* Returns the DIE for TYPE.  A DIE is always returned.  */
+/* Returns the DIE for TYPE, that must not be a base type.  A DIE is
+   always returned.  */
 
 static dw_die_ref
 force_type_die (tree type)
@@ -13307,13 +13625,22 @@ dwarf2out_imported_module_or_decl (tree decl, tree context)
   if (!context)
     scope_die = comp_unit_die;
   else if (TYPE_P (context))
+    {
+      if (!should_emit_struct_debug (context, DINFO_USAGE_DIR_USE))
+       return;
     scope_die = force_type_die (context);
+    }
   else
     scope_die = force_decl_die (context);
 
   /* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE.  */
   if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
-    at_import_die = force_type_die (TREE_TYPE (decl));
+    {
+      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));
+    }
   else
     {
       at_import_die = lookup_decl_die (decl);
@@ -13328,7 +13655,12 @@ dwarf2out_imported_module_or_decl (tree decl, tree context)
 
              if (TYPE_CONTEXT (type))
                if (TYPE_P (TYPE_CONTEXT (type)))
+                 {
+                   if (!should_emit_struct_debug (TYPE_CONTEXT (type),
+                                                  DINFO_USAGE_DIR_USE))
+                     return;
                  type_context_die = force_type_die (TYPE_CONTEXT (type));
+                 }
              else
                type_context_die = force_decl_die (TYPE_CONTEXT (type));
              else
@@ -13429,7 +13761,7 @@ dwarf2out_decl (tree decl)
       if (debug_info_level <= DINFO_LEVEL_TERSE)
        return;
       if (lookup_decl_die (decl) != NULL)
-        return;
+       return;
       break;
 
     case TYPE_DECL:
@@ -13580,7 +13912,7 @@ maybe_emit_file (struct dwarf_file_data * fd)
       else
        fd->emitted_number = 1;
       last_emitted_file = fd;
-      
+
       if (DWARF2_ASM_LINE_DEBUG_INFO)
        {
          fprintf (asm_out_file, "\t.file %u ", fd->emitted_number);
@@ -13588,7 +13920,7 @@ maybe_emit_file (struct dwarf_file_data * fd)
          fputc ('\n', asm_out_file);
        }
     }
-  
+
   return fd->emitted_number;
 }
 
@@ -13617,7 +13949,7 @@ dwarf2out_var_location (rtx loc_note)
   if (last_insn != NULL_RTX
       && last_insn == prev_insn
       && NOTE_P (prev_insn)
-      && NOTE_LINE_NUMBER (prev_insn) == NOTE_INSN_VAR_LOCATION)
+      && NOTE_KIND (prev_insn) == NOTE_INSN_VAR_LOCATION)
     {
       newloc->label = last_label;
     }
@@ -13651,7 +13983,7 @@ static void
 dwarf2out_begin_function (tree fun)
 {
   htab_empty (decl_loc_table);
-  
+
   if (function_section (fun) != text_section)
     have_multiple_function_sections = true;
 }
@@ -13667,7 +13999,7 @@ dwarf2out_source_line (unsigned int line, const char *filename)
       && line != 0)
     {
       int file_num = maybe_emit_file (lookup_filename (filename));
-      
+
       switch_to_section (current_function_section ());
 
       /* If requested, emit something human-readable.  */
@@ -13686,7 +14018,7 @@ dwarf2out_source_line (unsigned int line, const char *filename)
       else if (function_section (current_function_decl) != text_section)
        {
          dw_separate_line_info_ref line_info;
-         targetm.asm_out.internal_label (asm_out_file, 
+         targetm.asm_out.internal_label (asm_out_file,
                                          SEPARATE_LINE_CODE_LABEL,
                                          separate_line_info_table_in_use);
 
@@ -13852,6 +14184,10 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   /* Zero-th entry is allocated, but unused.  */
   line_info_table_in_use = 1;
 
+  /* Allocate the pubtypes and pubnames vectors.  */
+  pubname_table = VEC_alloc (pubname_entry, gc, 32);
+  pubtype_table = VEC_alloc (pubname_entry, gc, 32);
+
   /* Generate the initial DIE for the .debug section.  Note that the (string)
      value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE
      will (typically) be a relative pathname and that this pathname should be
@@ -13878,6 +14214,10 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
                                   SECTION_DEBUG, NULL);
   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
                                        SECTION_DEBUG, NULL);
+#ifdef DEBUG_PUBTYPES_SECTION
+  debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
+                                       SECTION_DEBUG, NULL);
+#endif
   debug_str_section = get_section (DEBUG_STR_SECTION,
                                   DEBUG_STR_SECTION_FLAGS, NULL);
   debug_ranges_section = get_section (DEBUG_RANGES_SECTION,
@@ -13889,7 +14229,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
                               DEBUG_ABBREV_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
-  ASM_GENERATE_INTERNAL_LABEL (cold_text_section_label, 
+  ASM_GENERATE_INTERNAL_LABEL (cold_text_section_label,
                               COLD_TEXT_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (cold_end_label, COLD_END_LABEL, 0);
 
@@ -13948,7 +14288,7 @@ static void
 verify_marks_clear (dw_die_ref die)
 {
   dw_die_ref c;
-  
+
   gcc_assert (! die->die_mark);
   FOR_EACH_CHILD (die, c, verify_marks_clear (c));
 }
@@ -13961,7 +14301,7 @@ static void
 prune_unmark_dies (dw_die_ref die)
 {
   dw_die_ref c;
-  
+
   if (die->die_mark)
     die->die_mark = 0;
   FOR_EACH_CHILD (die, c, prune_unmark_dies (c));
@@ -14014,9 +14354,9 @@ prune_unused_types_mark (dw_die_ref die, int dokids)
       prune_unused_types_walk_attribs (die);
 
       /* If this node is a specification,
-         also mark the definition, if it exists.  */
+        also mark the definition, if it exists.  */
       if (get_AT_flag (die, DW_AT_declaration) && die->die_definition)
-        prune_unused_types_mark (die->die_definition, 1);
+       prune_unused_types_mark (die->die_definition, 1);
     }
 
   if (dokids && die->die_mark != 2)
@@ -14046,35 +14386,36 @@ prune_unused_types_walk (dw_die_ref die)
   if (die->die_mark)
     return;
 
-  switch (die->die_tag) {
-  case DW_TAG_const_type:
-  case DW_TAG_packed_type:
-  case DW_TAG_pointer_type:
-  case DW_TAG_reference_type:
-  case DW_TAG_volatile_type:
-  case DW_TAG_typedef:
-  case DW_TAG_array_type:
-  case DW_TAG_structure_type:
-  case DW_TAG_union_type:
-  case DW_TAG_class_type:
-  case DW_TAG_friend:
-  case DW_TAG_variant_part:
-  case DW_TAG_enumeration_type:
-  case DW_TAG_subroutine_type:
-  case DW_TAG_string_type:
-  case DW_TAG_set_type:
-  case DW_TAG_subrange_type:
-  case DW_TAG_ptr_to_member_type:
-  case DW_TAG_file_type:
-    if (die->die_perennial_p)
-      break;
+  switch (die->die_tag)
+    {
+    case DW_TAG_const_type:
+    case DW_TAG_packed_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_reference_type:
+    case DW_TAG_volatile_type:
+    case DW_TAG_typedef:
+    case DW_TAG_array_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_class_type:
+    case DW_TAG_friend:
+    case DW_TAG_variant_part:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_subroutine_type:
+    case DW_TAG_string_type:
+    case DW_TAG_set_type:
+    case DW_TAG_subrange_type:
+    case DW_TAG_ptr_to_member_type:
+    case DW_TAG_file_type:
+      if (die->die_perennial_p)
+       break;
 
-    /* It's a type node --- don't mark it.  */
-    return;
+      /* It's a type node --- don't mark it.  */
+      return;
 
-  default:
-    /* Mark everything else.  */
-    break;
+    default:
+      /* Mark everything else.  */
+      break;
   }
 
   die->die_mark = 1;
@@ -14127,7 +14468,7 @@ prune_unused_types_prune (dw_die_ref die)
 
   if (! die->die_child)
     return;
-  
+
   c = die->die_child;
   do {
     dw_die_ref prev = c;
@@ -14160,6 +14501,7 @@ prune_unused_types (void)
 {
   unsigned int i;
   limbo_die_node *node;
+  pubname_ref pub;
 
 #if ENABLE_ASSERT_CHECKING
   /* All the marks should already be clear.  */
@@ -14175,8 +14517,8 @@ prune_unused_types (void)
 
   /* Also set the mark on nodes referenced from the
      pubname_table or arange_table.  */
-  for (i = 0; i < pubname_table_in_use; i++)
-    prune_unused_types_mark (pubname_table[i].die, 1);
+  for (i = 0; VEC_iterate (pubname_entry, pubname_table, i, pub); i++)
+    prune_unused_types_mark (pub->die, 1);
   for (i = 0; i < arange_table_in_use; i++)
     prune_unused_types_mark (arange_table[i], 1);
 
@@ -14272,7 +14614,9 @@ dwarf2out_finish (const char *filename)
              else if (TYPE_P (node->created_for))
                context = TYPE_CONTEXT (node->created_for);
 
-             gcc_assert (context && TREE_CODE (context) == FUNCTION_DECL);
+             gcc_assert (context
+                         && (TREE_CODE (context) == FUNCTION_DECL
+                             || TREE_CODE (context) == NAMESPACE_DECL));
 
              origin = lookup_decl_die (context);
              if (origin)
@@ -14320,10 +14664,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)
@@ -14355,12 +14732,21 @@ dwarf2out_finish (const char *filename)
   output_abbrev_section ();
 
   /* Output public names table if necessary.  */
-  if (pubname_table_in_use)
+  if (!VEC_empty (pubname_entry, pubname_table))
     {
       switch_to_section (debug_pubnames_section);
-      output_pubnames ();
+      output_pubnames (pubname_table);
     }
 
+#ifdef DEBUG_PUBTYPES_SECTION
+  /* Output public types table if necessary.  */
+  if (!VEC_empty (pubname_entry, pubtype_table))
+    {
+      switch_to_section (debug_pubtypes_section);
+      output_pubnames (pubtype_table);
+    }
+#endif
+
   /* Output the address range information.  We only put functions in the arange
      table, so don't write it out if we don't have any.  */
   if (fde_table_in_use)