OSDN Git Service

PR target/21723
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 70ad887..e7c4adb 100644 (file)
@@ -19,8 +19,8 @@ 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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* TODO: Emit .debug_line header even when there are no functions, since
           the file numbers are used by .debug_info.  Alternately, leave
@@ -170,21 +170,25 @@ default_eh_frame_section (void)
 #endif
 }
 
+DEF_VEC_P(rtx);
+DEF_VEC_ALLOC_P(rtx,gc);
+
 /* Array of RTXes referenced by the debugging information, which therefore
    must be kept around forever.  */
-static GTY(()) varray_type used_rtx_varray;
+static GTY(()) VEC(rtx,gc) *used_rtx_array;
 
 /* A pointer to the base of a list of incomplete types which might be
-   completed at some later time.  incomplete_types_list needs to be a VARRAY
-   because we want to tell the garbage collector about it.  */
-static GTY(()) varray_type incomplete_types;
+   completed at some later time.  incomplete_types_list needs to be a
+   VEC(tree,gc) because we want to tell the garbage collector about
+   it.  */
+static GTY(()) VEC(tree,gc) *incomplete_types;
 
 /* A pointer to the base of a table of references to declaration
    scopes.  This table is a display which tracks the nesting
    of declaration scopes at the current scope and containing
    scopes.  This table is used to find the proper place to
    define type declaration DIE's.  */
-static GTY(()) varray_type decl_scope_table;
+static GTY(()) VEC(tree,gc) *decl_scope_table;
 
 /* How to start an assembler comment.  */
 #ifndef ASM_COMMENT_START
@@ -253,6 +257,11 @@ typedef struct dw_fde_struct GTY(())
   const char *dw_fde_begin;
   const char *dw_fde_current_label;
   const char *dw_fde_end;
+  const char *dw_fde_hot_section_label;
+  const char *dw_fde_hot_section_end_label;
+  const char *dw_fde_unlikely_section_label;
+  const char *dw_fde_unlikely_section_end_label;
+  bool dw_fde_switched_sections;
   dw_cfi_ref dw_fde_cfi;
   unsigned funcdef_number;
   unsigned all_throwers_are_sibcalls : 1;
@@ -490,7 +499,8 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
        if (offset < 0)
          continue;
 
-       emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
+       emit_move_insn (adjust_address (mem, mode, offset),
+                       gen_int_mode (size, mode));
       }
 
 #ifdef DWARF_ALT_FRAME_RETURN_COLUMN
@@ -1477,7 +1487,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
   src = SET_SRC (expr);
   dest = SET_DEST (expr);
 
-  if (GET_CODE (src) == REG)
+  if (REG_P (src))
     {
       rtx rsi = reg_saved_in (src);
       if (rsi)
@@ -2069,6 +2079,7 @@ output_call_frame_info (int for_eh)
   int fde_encoding = DW_EH_PE_absptr;
   int per_encoding = DW_EH_PE_absptr;
   int lsda_encoding = DW_EH_PE_absptr;
+  int return_reg;
 
   /* Don't emit a CIE if there won't be any FDEs.  */
   if (fde_table_in_use == 0)
@@ -2207,10 +2218,11 @@ output_call_frame_info (int for_eh)
   dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT,
                               "CIE Data Alignment Factor");
 
+  return_reg = DWARF2_FRAME_REG_OUT (DWARF_FRAME_RETURN_COLUMN, for_eh);
   if (DW_CIE_VERSION == 1)
-    dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
+    dw2_asm_output_data (1, return_reg, "CIE RA Column");
   else
-    dw2_asm_output_data_uleb128 (DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
+    dw2_asm_output_data_uleb128 (return_reg, "CIE RA Column");
 
   if (augmentation[0])
     {
@@ -2273,17 +2285,57 @@ output_call_frame_info (int for_eh)
          dw2_asm_output_encoded_addr_rtx (fde_encoding,
                                           sym_ref,
                                           "FDE initial location");
-         dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
-                               fde->dw_fde_end, fde->dw_fde_begin,
-                               "FDE address range");
+         if (fde->dw_fde_switched_sections)
+           {
+             rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode, 
+                                     fde->dw_fde_unlikely_section_label);
+             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;
+             dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref3,
+                                              "FDE initial location");
+             dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
+                                   fde->dw_fde_hot_section_end_label,
+                                   fde->dw_fde_hot_section_label,
+                                   "FDE address range");
+             dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref2,
+                                              "FDE initial location");
+             dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
+                                   fde->dw_fde_unlikely_section_end_label,
+                                   fde->dw_fde_unlikely_section_label,
+                                   "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");
        }
       else
        {
          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 (fde->dw_fde_switched_sections)
+           {
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE,
+                                  fde->dw_fde_hot_section_label,
+                                  "FDE initial location");
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                                   fde->dw_fde_hot_section_end_label,
+                                   fde->dw_fde_hot_section_label,
+                                   "FDE address range");
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE,
+                                  fde->dw_fde_unlikely_section_label,
+                                  "FDE initial location");
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE, 
+                                   fde->dw_fde_unlikely_section_end_label,
+                                   fde->dw_fde_unlikely_section_label,
+                                   "FDE address range");
+           }
+         else
+           dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                                 fde->dw_fde_end, fde->dw_fde_begin,
+                                 "FDE address range");
        }
 
       if (augmentation[0])
@@ -2409,6 +2461,11 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
   fde->decl = current_function_decl;
   fde->dw_fde_begin = dup_label;
   fde->dw_fde_current_label = NULL;
+  fde->dw_fde_hot_section_label = NULL;
+  fde->dw_fde_hot_section_end_label = NULL;
+  fde->dw_fde_unlikely_section_label = NULL;
+  fde->dw_fde_unlikely_section_end_label = NULL;
+  fde->dw_fde_switched_sections = false;
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
   fde->funcdef_number = current_function_funcdef_no;
@@ -2940,7 +2997,6 @@ new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
   return descr;
 }
 
-
 /* Add a location description term to a location description expression.  */
 
 static inline void
@@ -3206,13 +3262,15 @@ output_loc_operands (dw_loc_descr_ref loc)
       break;
 
     case INTERNAL_DW_OP_tls_addr:
-#ifdef ASM_OUTPUT_DWARF_DTPREL
-      ASM_OUTPUT_DWARF_DTPREL (asm_out_file, DWARF2_ADDR_SIZE,
-                              val1->v.val_addr);
-      fputc ('\n', asm_out_file);
-#else
-      gcc_unreachable ();
-#endif
+      if (targetm.asm_out.output_dwarf_dtprel)
+       {
+         targetm.asm_out.output_dwarf_dtprel (asm_out_file,
+                                              DWARF2_ADDR_SIZE,
+                                              val1->v.val_addr);
+         fputc ('\n', asm_out_file);
+       }
+      else
+       gcc_unreachable ();
       break;
 
     default:
@@ -3390,7 +3448,7 @@ get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_struct *loc)
          cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
          break;
        default:
-         internal_error ("DW_LOC_OP %s not implemented\n",
+         internal_error ("DW_LOC_OP %s not implemented",
                          dwarf_stack_op_name (ptr->dw_loc_opc));
        }
     }
@@ -3418,6 +3476,7 @@ 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.  */
 
@@ -3450,6 +3509,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   debug_nothing_rtx,           /* label */
   debug_nothing_int,           /* handle_pch */
   dwarf2out_var_location,
+  dwarf2out_switch_text_section,
   1                             /* start_end_main_source_file */
 };
 #endif
@@ -3651,6 +3711,7 @@ struct var_loc_node GTY ((chain_next ("%h.next")))
 {
   rtx GTY (()) var_loc_note;
   const char * GTY (()) label;
+  const char * GTY (()) section_label;
   struct var_loc_node * GTY (()) next;
 };
 
@@ -3913,6 +3974,7 @@ 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 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);
@@ -4069,6 +4131,9 @@ static int maybe_emit_file (int);
 #ifndef TEXT_SECTION_LABEL
 #define TEXT_SECTION_LABEL             "Ltext"
 #endif
+#ifndef COLD_TEXT_SECTION_LABEL
+#define COLD_TEXT_SECTION_LABEL         "Ltext_cold"
+#endif
 #ifndef DEBUG_LINE_SECTION_LABEL
 #define DEBUG_LINE_SECTION_LABEL       "Ldebug_line"
 #endif
@@ -4096,6 +4161,8 @@ static int maybe_emit_file (int);
 
 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 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];
@@ -4106,6 +4173,9 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 #ifndef TEXT_END_LABEL
 #define TEXT_END_LABEL         "Letext"
 #endif
+#ifndef COLD_END_LABEL
+#define COLD_END_LABEL          "Letext_cold"
+#endif
 #ifndef BLOCK_BEGIN_LABEL
 #define BLOCK_BEGIN_LABEL      "LBB"
 #endif
@@ -6742,6 +6812,22 @@ 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;
+  separate_line_info_table_in_use++;
+}
+
 /* Output the location list given to us.  */
 
 static void
@@ -7170,6 +7256,13 @@ output_aranges (void)
   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)
+    {
+      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");
+    }
 
   for (i = 0; i < arange_table_in_use; i++)
     {
@@ -7648,7 +7741,14 @@ output_line_info (void)
      a series of state machine operations.  */
   current_file = 1;
   current_line = 1;
-  strcpy (prev_line_label, text_section_label);
+
+  if (cfun
+      && (last_text_section == in_unlikely_executed_text
+         || (last_text_section == in_named
+             && last_text_section_name == cfun->unlikely_text_section_name)))
+    strcpy (prev_line_label, cfun->cold_section_label);
+  else
+    strcpy (prev_line_label, text_section_label);
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
       dw_line_info_ref line_info = &line_info_table[lt_index];
@@ -8311,6 +8411,26 @@ dbx_reg_number (rtx rtl)
   return DBX_REGISTER_NUMBER (regno);
 }
 
+/* Optionally add a DW_OP_piece term to a location description expression.
+   DW_OP_piece is only added if the location description expression already
+   doesn't end with DW_OP_piece.  */
+
+static void
+add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
+{
+  dw_loc_descr_ref loc;
+
+  if (*list_head != NULL)
+    {
+      /* Find the end of the chain.  */
+      for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
+       ;
+
+      if (loc->dw_loc_opc != DW_OP_piece)
+       loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0);
+    }
+}
+
 /* Return a location descriptor that designates a machine register or
    zero if there is none.  */
 
@@ -8370,7 +8490,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
 
          t = one_reg_loc_descriptor (reg);
          add_loc_descr (&loc_result, t);
-         add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+         add_loc_descr_op_piece (&loc_result, size);
          ++reg;
        }
       return loc_result;
@@ -8390,7 +8510,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
       t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)));
       add_loc_descr (&loc_result, t);
       size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
-      add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+      add_loc_descr_op_piece (&loc_result, size);
     }
   return loc_result;
 }
@@ -8585,7 +8705,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
       mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
       mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
       mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl;
-      VARRAY_PUSH_RTX (used_rtx_varray, rtl);
+      VEC_safe_push (rtx, gc, used_rtx_array, rtl);
       break;
 
     case PRE_MODIFY:
@@ -8693,14 +8813,10 @@ concat_loc_descriptor (rtx x0, rtx x1)
     return 0;
 
   cc_loc_result = x0_ref;
-  add_loc_descr (&cc_loc_result,
-                new_loc_descr (DW_OP_piece,
-                               GET_MODE_SIZE (GET_MODE (x0)), 0));
+  add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
 
   add_loc_descr (&cc_loc_result, x1_ref);
-  add_loc_descr (&cc_loc_result,
-                new_loc_descr (DW_OP_piece,
-                               GET_MODE_SIZE (GET_MODE (x1)), 0));
+  add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
 
   return cc_loc_result;
 }
@@ -8765,8 +8881,7 @@ loc_descriptor (rtx rtl, bool can_use_fbreg)
        loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
                                     can_use_fbreg);
        mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
-       add_loc_descr (&loc_result,
-                      new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
+       add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
        for (i = 1; i < num_elem; i++)
          {
            dw_loc_descr_ref temp;
@@ -8775,9 +8890,7 @@ loc_descriptor (rtx rtl, bool can_use_fbreg)
                                   can_use_fbreg);
            add_loc_descr (&loc_result, temp);
            mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
-           add_loc_descr (&loc_result,
-                          new_loc_descr (DW_OP_piece,
-                                         GET_MODE_SIZE (mode), 0));
+           add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
          }
       }
       break;
@@ -8838,14 +8951,13 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1);
 
     case VAR_DECL:
-      if (DECL_THREAD_LOCAL (loc))
+      if (DECL_THREAD_LOCAL_P (loc))
        {
          rtx rtl;
 
-#ifndef ASM_OUTPUT_DWARF_DTPREL
          /* If this is not defined, we have no way to emit the data.  */
-         return 0;
-#endif
+         if (!targetm.asm_out.output_dwarf_dtprel)
+           return 0;
 
          /* The way DW_OP_GNU_push_tls_address is specified, we can only
             look up addresses of objects in the current module.  */
@@ -8875,8 +8987,9 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
       /* FALLTHRU */
 
     case PARM_DECL:
-      if (DECL_VALUE_EXPR (loc))
-       return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc), want_address);
+      if (DECL_HAS_VALUE_EXPR_P (loc))
+       return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc),
+                                          want_address);
       /* FALLTHRU */
 
     case RESULT_DECL:
@@ -9191,7 +9304,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
 
 #ifdef ENABLE_CHECKING
       /* Otherwise this is a generic code; we should just lists all of
-        these explicitly.  Aborting means we forgot one.  */
+        these explicitly.  We forgot one.  */
       gcc_unreachable ();
 #else
       /* In a release build, we want to degrade gracefully: better to
@@ -9677,7 +9790,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
     case LABEL_REF:
     case CONST:
       add_AT_addr (die, DW_AT_const_value, rtl);
-      VARRAY_PUSH_RTX (used_rtx_varray, rtl);
+      VEC_safe_push (rtx, gc, used_rtx_array, rtl);
       break;
 
     case PLUS:
@@ -9701,6 +9814,53 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
 
 }
 
+/* Generate an RTL constant from a decl initializer INIT with decl type TYPE,
+   for use in a later add_const_value_attribute call.  */
+
+static rtx
+rtl_for_decl_init (tree init, tree type)
+{
+  rtx rtl = NULL_RTX;
+
+  /* If a variable is initialized with a string constant without embedded
+     zeros, build CONST_STRING.  */
+  if (TREE_CODE (init) == STRING_CST && TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree enttype = TREE_TYPE (type);
+      tree domain = TYPE_DOMAIN (type);
+      enum machine_mode mode = TYPE_MODE (enttype);
+
+      if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+         && domain
+         && integer_zerop (TYPE_MIN_VALUE (domain))
+         && compare_tree_int (TYPE_MAX_VALUE (domain),
+                              TREE_STRING_LENGTH (init) - 1) == 0
+         && ((size_t) TREE_STRING_LENGTH (init)
+             == strlen (TREE_STRING_POINTER (init)) + 1))
+       rtl = gen_rtx_CONST_STRING (VOIDmode,
+                                   ggc_strdup (TREE_STRING_POINTER (init)));
+    }
+  /* If the initializer is something that we know will expand into an
+     immediate RTL constant, expand it now.  Expanding anything else
+     tends to produce unresolved symbols; see debug/5770 and c++/6381.  */
+  /* Aggregate, vector, and complex types may contain constructors that may
+     result in code being generated when expand_expr is called, so we can't
+     handle them here.  Integer and float are useful and safe types to handle
+     here.  */
+  else if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))
+          && initializer_constant_valid_p (init, type) == null_pointer_node)
+    {
+      rtl = expand_expr (init, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+
+      /* If expand_expr returns a MEM, it wasn't immediate.  */
+      gcc_assert (!rtl || !MEM_P (rtl));
+    }
+
+  return rtl;
+}
+
+/* Generate RTL for the variable DECL to represent its location.  */
+
 static rtx
 rtl_for_decl_location (tree decl)
 {
@@ -9896,40 +10056,7 @@ rtl_for_decl_location (tree decl)
      and will have been substituted directly into all expressions that use it.
      C does not have such a concept, but C++ and other languages do.  */
   else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
-    {
-      /* If a variable is initialized with a string constant without embedded
-        zeros, build CONST_STRING.  */
-      if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
-         && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-       {
-         tree arrtype = TREE_TYPE (decl);
-         tree enttype = TREE_TYPE (arrtype);
-         tree domain = TYPE_DOMAIN (arrtype);
-         tree init = DECL_INITIAL (decl);
-         enum machine_mode mode = TYPE_MODE (enttype);
-
-         if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
-             && domain
-             && integer_zerop (TYPE_MIN_VALUE (domain))
-             && compare_tree_int (TYPE_MAX_VALUE (domain),
-                                  TREE_STRING_LENGTH (init) - 1) == 0
-             && ((size_t) TREE_STRING_LENGTH (init)
-                 == strlen (TREE_STRING_POINTER (init)) + 1))
-           rtl = gen_rtx_CONST_STRING (VOIDmode,
-                                       ggc_strdup (TREE_STRING_POINTER (init)));
-       }
-      /* If the initializer is something that we know will expand into an
-        immediate RTL constant, expand it now.  Expanding anything else
-        tends to produce unresolved symbols; see debug/5770 and c++/6381.  */
-      else if (TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST
-              || TREE_CODE (DECL_INITIAL (decl)) == REAL_CST)
-       {
-         rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
-                            EXPAND_INITIALIZER);
-         /* If expand_expr returns a MEM, it wasn't immediate.  */
-         gcc_assert (!rtl || !MEM_P (rtl));
-       }
-    }
+    rtl = rtl_for_decl_init (DECL_INITIAL (decl), TREE_TYPE (decl));
 
   if (rtl)
     rtl = targetm.delegitimize_address (rtl);
@@ -10006,7 +10133,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
       dw_loc_list_ref list;
       rtx varloc;
 
-
       /* We need to figure out what section we should use as the base
         for the address ranges where a given location is valid.
         1. If this particular DECL has a section associated with it,
@@ -10028,6 +10154,12 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
          tree sectree = DECL_SECTION_NAME (current_function_decl);
          secname = TREE_STRING_POINTER (sectree);
        }
+      else if (cfun
+              && (last_text_section == in_unlikely_executed_text
+                  || (last_text_section == in_named
+                      && last_text_section_name == 
+                      cfun->unlikely_text_section_name)))
+       secname = cfun->cold_section_label;
       else
        secname = text_section_label;
 
@@ -10127,27 +10259,16 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
 {
   tree init = DECL_INITIAL (decl);
   tree type = TREE_TYPE (decl);
+  rtx rtl;
 
-  if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init
-      && initializer_constant_valid_p (init, type) == null_pointer_node)
+  if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init)
     /* OK */;
   else
     return;
 
-  switch (TREE_CODE (type))
-    {
-    case INTEGER_TYPE:
-      if (host_integerp (init, 0))
-       add_AT_unsigned (var_die, DW_AT_const_value,
-                        tree_low_cst (init, 0));
-      else
-       add_AT_long_long (var_die, DW_AT_const_value,
-                         TREE_INT_CST_HIGH (init),
-                         TREE_INT_CST_LOW (init));
-      break;
-
-    default:;
-    }
+  rtl = rtl_for_decl_init (init, type);
+  if (rtl)
+    add_const_value_attribute (var_die, rtl);
 }
 
 /* Generate a DW_AT_name attribute given some string value to be included as
@@ -10470,11 +10591,7 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
       if (TYPE_P (fn))
        fn = TYPE_STUB_DECL (fn);
       
-      /* TYPE_STUB_DECL may have given us a NULL, which decl_function_context
-        won't like.  */
-      if (fn)  
-       fn = decl_function_context (fn);
-
+      fn = decl_function_context (fn);
       if (fn)
        dwarf2out_abstract_function (fn);
     }
@@ -10488,7 +10605,7 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
      trees (in the case of java, they simply have no block tree, in some other
      languages).  For these functions, there is nothing we can really do to
      output correct debug info for inlined functions in all cases.  Rather
-     than abort, we'll just produce deficient debug info now, in that we will
+     than die, we'll just produce deficient debug info now, in that we will
      have variables without a proper abstract origin.  In the future, when all
      functions are lowered, we should re-add a gcc_assert (origin_die)
      here.  */
@@ -10561,7 +10678,7 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
     {
       add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address,
                   XEXP (DECL_RTL (decl), 0));
-      VARRAY_PUSH_RTX (used_rtx_varray, XEXP (DECL_RTL (decl), 0));
+      VEC_safe_push (tree, gc, used_rtx_array, XEXP (DECL_RTL (decl), 0));
     }
 #endif
 }
@@ -10571,7 +10688,7 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
 static void
 push_decl_scope (tree scope)
 {
-  VARRAY_PUSH_TREE (decl_scope_table, scope);
+  VEC_safe_push (tree, gc, decl_scope_table, scope);
 }
 
 /* Pop a declaration scope.  */
@@ -10579,9 +10696,7 @@ push_decl_scope (tree scope)
 static inline void
 pop_decl_scope (void)
 {
-  gcc_assert (VARRAY_ACTIVE_SIZE (decl_scope_table) > 0);
-
-  VARRAY_POP (decl_scope_table);
+  VEC_pop (tree, decl_scope_table);
 }
 
 /* Return the DIE for the scope that immediately contains this type.
@@ -10624,8 +10739,8 @@ scope_die_for (tree t, dw_die_ref context_die)
       /* For types, we can just look up the appropriate DIE.  But
         first we check to see if we're in the middle of emitting it
         so we know where the new DIE should go.  */
-      for (i = VARRAY_ACTIVE_SIZE (decl_scope_table) - 1; i >= 0; --i)
-       if (VARRAY_TREE (decl_scope_table, i) == containing_scope)
+      for (i = VEC_length (tree, decl_scope_table) - 1; i >= 0; --i)
+       if (VEC_index (tree, decl_scope_table, i) == containing_scope)
          break;
 
       if (i < 0)
@@ -10881,8 +10996,8 @@ retry_incomplete_types (void)
 {
   int i;
 
-  for (i = VARRAY_ACTIVE_SIZE (incomplete_types) - 1; i >= 0; i--)
-    gen_type_die (VARRAY_TREE (incomplete_types, i), comp_unit_die);
+  for (i = VEC_length (tree, incomplete_types) - 1; i >= 0; i--)
+    gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die);
 }
 
 /* Generate a DIE to represent an inlined instance of an enumeration type.  */
@@ -11124,13 +11239,27 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
   if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))
       && ! lookup_decl_die (member))
     {
+      dw_die_ref type_die;
       gcc_assert (!decl_ultimate_origin (member));
 
       push_decl_scope (type);
+      type_die = lookup_type_die (type);
       if (TREE_CODE (member) == FUNCTION_DECL)
-       gen_subprogram_die (member, lookup_type_die (type));
+       gen_subprogram_die (member, type_die);
+      else if (TREE_CODE (member) == FIELD_DECL)
+       {
+         /* Ignore the nameless fields that are used to skip bits but handle
+            C++ anonymous unions and structs.  */
+         if (DECL_NAME (member) != NULL_TREE
+             || TREE_CODE (TREE_TYPE (member)) == UNION_TYPE
+             || TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE)
+           {
+             gen_type_die (member_declared_type (member), type_die);
+             gen_field_die (member, type_die);
+           }
+       }
       else
-       gen_variable_die (member, lookup_type_die (type));
+       gen_variable_die (member, type_die);
 
       pop_decl_scope ();
     }
@@ -11334,15 +11463,33 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (!old_die || !get_AT (old_die, DW_AT_inline))
        equate_decl_number_to_die (decl, subr_die);
 
-      ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
-                                  current_function_funcdef_no);
-      add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
-      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);
+      if (!flag_reorder_blocks_and_partition)
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
+                                      current_function_funcdef_no);
+         add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
+         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);
+       }
+      else
+       {  /* Do nothing for now; maybe need to duplicate die, one for
+             hot section and ond for cold section, then use the hot/cold
+             section begin/end labels to generate the aranges...  */
+         /*
+           add_AT_lbl_id (subr_die, DW_AT_low_pc, hot_section_label);
+           add_AT_lbl_id (subr_die, DW_AT_high_pc, hot_section_end_label);
+           add_AT_lbl_id (subr_die, DW_AT_lo_user, unlikely_section_label);
+           add_AT_lbl_id (subr_die, DW_AT_hi_user, cold_section_end_label);
+
+           add_pubname (decl, subr_die);
+           add_arange (decl, subr_die);
+           add_arange (decl, subr_die);
+          */
+       }
 
 #ifdef MIPS_DEBUGGING_INFO
       /* Add a reference to the FDE for this routine.  */
@@ -11488,8 +11635,13 @@ gen_variable_die (tree decl, dw_die_ref context_die)
      copy decls and set the DECL_ABSTRACT flag on them instead of
      sharing them.
 
-     ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
-  else if (old_die && TREE_STATIC (decl)
+     ??? Duplicated blocks have been rewritten to use .debug_ranges.
+
+     ??? The declare_in_namespace support causes us to get two DIEs for one
+     variable, both of which are declarations.  We want to avoid considering
+     one to be a specification, so we must test that this DIE is not a
+     declaration.  */
+  else if (old_die && TREE_STATIC (decl) && ! declaration
           && get_AT_flag (old_die, DW_AT_declaration) == 1)
     {
       /* This is a definition of a C++ class level static.  */
@@ -11872,7 +12024,7 @@ gen_member_die (tree type, dw_die_ref context_die)
   /* First output info about the base classes.  */
   if (binfo)
     {
-      VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo);
+      VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
       int i;
       tree base;
 
@@ -11991,7 +12143,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
       /* We don't need to do this for function-local types.  */
       if (TYPE_STUB_DECL (type)
          && ! decl_function_context (TYPE_STUB_DECL (type)))
-       VARRAY_PUSH_TREE (incomplete_types, type);
+       VEC_safe_push (tree, gc, incomplete_types, type);
     }
 }
 
@@ -12372,6 +12524,11 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
          
          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. */
+         if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+           ;
          else
            gen_decl_die (decl, context_die);
        }
@@ -12408,7 +12565,7 @@ is_redundant_typedef (tree decl)
   return 0;
 }
 
-/* Returns the DIE for decl or aborts.  */
+/* Returns the DIE for decl.  A DIE will always be returned.  */
 
 static dw_die_ref
 force_decl_die (tree decl)
@@ -12461,8 +12618,7 @@ force_decl_die (tree decl)
          gcc_unreachable ();
        }
 
-      /* See if we can find the die for this deci now.
-        If not then abort.  */
+      /* We should be able to find the DIE now.  */
       if (!decl_die)
        decl_die = lookup_decl_die (decl);
       gcc_assert (decl_die);
@@ -12471,7 +12627,7 @@ force_decl_die (tree decl)
   return decl_die;
 }
 
-/* Returns the DIE for decl or aborts.  */
+/* Returns the DIE for TYPE.  A DIE is always returned.  */
 
 static dw_die_ref
 force_type_die (tree type)
@@ -12819,7 +12975,29 @@ dwarf2out_imported_module_or_decl (tree decl, tree context)
   if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
     at_import_die = force_type_die (TREE_TYPE (decl));
   else
-    at_import_die = force_decl_die (decl);
+    {
+      at_import_die = lookup_decl_die (decl);
+      if (!at_import_die)
+       {
+         /* If we're trying to avoid duplicate debug info, we may not have
+            emitted the member decl for this field.  Emit it now.  */
+         if (TREE_CODE (decl) == FIELD_DECL)
+           {
+             tree type = DECL_CONTEXT (decl);
+             dw_die_ref type_context_die;
+
+             if (TYPE_CONTEXT (type))
+               if (TYPE_P (TYPE_CONTEXT (type)))
+                 type_context_die = force_type_die (TYPE_CONTEXT (type));
+             else
+               type_context_die = force_decl_die (TYPE_CONTEXT (type));
+             else
+               type_context_die = comp_unit_die;
+             gen_type_die_for_member (type, decl, type_context_die);
+           }
+         at_import_die = force_decl_die (decl);
+       }
+    }
 
   /* OK, now we have DIEs for decl as well as scope. Emit imported die.  */
   if (TREE_CODE (decl) == NAMESPACE_DECL)
@@ -12898,6 +13076,10 @@ dwarf2out_decl (tree decl)
       if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
        return;
 
+      /* For local statics lookup proper context die.  */
+      if (TREE_STATIC (decl) && decl_function_context (decl))
+       context_die = lookup_decl_die (DECL_CONTEXT (decl));
+
       /* If we are in terse mode, don't generate any DIEs to represent any
         variable declarations or definitions.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
@@ -12956,7 +13138,7 @@ static void
 dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
                       unsigned int blocknum)
 {
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
 }
 
@@ -12966,7 +13148,7 @@ dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
 static void
 dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum)
 {
-  function_section (current_function_decl);
+  current_function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
 }
 
@@ -13032,6 +13214,14 @@ lookup_filename (const char *file_name)
   VARRAY_PUSH_CHAR_PTR (file_table, save_file_name);
   VARRAY_PUSH_UINT (file_table_emitted, 0);
 
+  /* If the assembler is emitting the file table, and we aren't eliminating
+     unused debug types, then we must emit .file here.  If we are eliminating
+     unused debug types, then this will be done by the maybe_emit_file call in
+     prune_unused_types_walk_attribs.  */
+
+  if (DWARF2_ASM_LINE_DEBUG_INFO && ! flag_eliminate_unused_debug_types)
+    maybe_emit_file (i);
+
   return i;
 }
 
@@ -13107,10 +13297,18 @@ dwarf2out_var_location (rtx loc_note)
   newloc->var_loc_note = loc_note;
   newloc->next = NULL;
 
+  if (cfun
+      && (last_text_section == in_unlikely_executed_text
+         || (last_text_section == in_named
+             && last_text_section_name == cfun->unlikely_text_section_name)))
+    newloc->section_label = cfun->cold_section_label;
+  else
+    newloc->section_label = text_section_label;
+
   last_insn = loc_note;
   last_label = newloc->label;
   decl = NOTE_VAR_LOCATION_DECL (loc_note);
-  if (DECL_DEBUG_EXPR (decl) && DECL_DEBUG_EXPR_IS_FROM (decl)
+  if (DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl) 
       && DECL_P (DECL_DEBUG_EXPR (decl)))
     decl = DECL_DEBUG_EXPR (decl); 
   add_var_loc_to_decl (decl, newloc);
@@ -13137,7 +13335,7 @@ dwarf2out_source_line (unsigned int line, const char *filename)
   if (debug_info_level >= DINFO_LEVEL_NORMAL
       && line != 0)
     {
-      function_section (current_function_decl);
+      current_function_section (current_function_decl);
 
       /* If requested, emit something human-readable.  */
       if (flag_debug_asm)
@@ -13308,7 +13506,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
                                    decl_loc_table_eq, NULL);
 
   /* Allocate the initial hunk of the decl_scope_table.  */
-  VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
+  decl_scope_table = VEC_alloc (tree, gc, 256);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
   abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT
@@ -13333,14 +13531,17 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
      in this value in dwarf2out_finish.  */
   comp_unit_die = gen_compile_unit_die (NULL);
 
-  VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types");
+  incomplete_types = VEC_alloc (tree, gc, 64);
 
-  VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
+  used_rtx_array = VEC_alloc (rtx, gc, 32);
 
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
   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, 
+                              COLD_TEXT_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (cold_end_label, COLD_END_LABEL, 0);
 
   ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
                               DEBUG_INFO_SECTION_LABEL, 0);
@@ -13365,6 +13566,11 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 
   text_section ();
   ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+  if (flag_reorder_blocks_and_partition)
+    {
+      unlikely_text_section ();
+      ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
+    }
 }
 
 /* A helper function for dwarf2out_finish called through
@@ -13696,6 +13902,11 @@ dwarf2out_finish (const char *filename)
   /* Output a terminator label for the .text section.  */
   text_section ();
   targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
+  if (flag_reorder_blocks_and_partition)
+    {
+      unlikely_text_section ();
+      targetm.asm_out.internal_label (asm_out_file, COLD_END_LABEL, 0);
+    }
 
   /* Output the source line correspondence table.  We must do this
      even if there is no line information.  Otherwise, on an empty