OSDN Git Service

Refine previous change.
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 9887fe4..88aea9b 100644 (file)
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "debug.h"
 #include "target.h"
+#include "common/common-target.h"
 #include "targhooks.h"
 #include "tree-mudflap.h"
 #include "cgraph.h"
@@ -121,10 +122,6 @@ static unsigned min_align (unsigned, unsigned);
 static void globalize_decl (tree);
 static bool decl_readonly_section_1 (enum section_category);
 #ifdef BSS_SECTION_ASM_OP
-#ifdef ASM_OUTPUT_BSS
-static void asm_output_bss (FILE *, tree, const char *,
-                           unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
-#endif
 #ifdef ASM_OUTPUT_ALIGNED_BSS
 static void asm_output_aligned_bss (FILE *, tree, const char *,
                                    unsigned HOST_WIDE_INT, int)
@@ -317,7 +314,11 @@ get_section (const char *name, unsigned int flags, tree decl)
          if (decl == 0)
            decl = sect->named.decl;
          gcc_assert (decl);
-         error ("%+D causes a section type conflict", decl);
+         error ("%+D causes a section type conflict with %D", 
+                       decl, sect->named.decl);
+         if (decl != sect->named.decl)
+            inform (DECL_SOURCE_LOCATION (sect->named.decl), 
+                   "%qD was declared here", sect->named.decl);
          /* Make sure we don't error about one section multiple times.  */
          sect->common.flags |= SECTION_OVERRIDE;
        }
@@ -416,7 +417,7 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
                        int flag_function_or_data_sections)
 {
   if (DECL_SECTION_NAME (decl) == NULL_TREE
-      && targetm.have_named_sections
+      && targetm_common.have_named_sections
       && (flag_function_or_data_sections
          || DECL_ONE_ONLY (decl)))
     {
@@ -427,34 +428,6 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
 
 #ifdef BSS_SECTION_ASM_OP
 
-#ifdef ASM_OUTPUT_BSS
-
-/* Utility function for ASM_OUTPUT_BSS for targets to use if
-   they don't support alignments in .bss.
-   ??? It is believed that this function will work in most cases so such
-   support is localized here.  */
-
-static void ATTRIBUTE_UNUSED
-asm_output_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
-               const char *name,
-               unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
-               unsigned HOST_WIDE_INT rounded)
-{
-  gcc_assert (strcmp (XSTR (XEXP (DECL_RTL (decl), 0), 0), name) == 0);
-  targetm.asm_out.globalize_decl_name (file, decl);
-  switch_to_section (bss_section);
-#ifdef ASM_DECLARE_OBJECT_NAME
-  last_assemble_variable_decl = decl;
-  ASM_DECLARE_OBJECT_NAME (file, name, decl);
-#else
-  /* Standard thing is just output label for the object.  */
-  ASM_OUTPUT_LABEL (file, name);
-#endif /* ASM_DECLARE_OBJECT_NAME */
-  ASM_OUTPUT_SKIP (file, rounded ? rounded : 1);
-}
-
-#endif
-
 #ifdef ASM_OUTPUT_ALIGNED_BSS
 
 /* Utility function for targets to use in implementing
@@ -492,7 +465,7 @@ hot_function_section (tree decl)
 {
   if (decl != NULL_TREE
       && DECL_SECTION_NAME (decl) != NULL_TREE
-      && targetm.have_named_sections)
+      && targetm_common.have_named_sections)
     return get_named_section (decl, NULL, 0);
   else
     return text_section;
@@ -564,7 +537,7 @@ default_function_section (tree decl, enum node_frequency freq,
 #endif
 
   if (!flag_reorder_functions
-      || !targetm.have_named_sections)
+      || !targetm_common.have_named_sections)
     return NULL;
   /* Startup code should go to startup subsection unless it is
      unlikely executed (this happens especially with function splitting
@@ -605,11 +578,14 @@ function_section_1 (tree decl, bool force_cold)
 
   if (decl)
     {
-      struct cgraph_node *node = cgraph_node (decl);
+      struct cgraph_node *node = cgraph_get_node (decl);
 
-      freq = node->frequency;
-      startup = node->only_called_at_startup;
-      exit = node->only_called_at_exit;
+      if (node)
+       {
+         freq = node->frequency;
+         startup = node->only_called_at_startup;
+         exit = node->only_called_at_exit;
+       }
     }
   if (force_cold)
     freq = NODE_FREQUENCY_UNLIKELY_EXECUTED;
@@ -766,7 +742,8 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
       const char *str;
       HOST_WIDE_INT i;
       int j, unit;
-      char name[30];
+      const char *prefix = targetm.asm_out.mergeable_rodata_prefix;
+      char *name = (char *) alloca (strlen (prefix) + 30);
 
       mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
       modesize = GET_MODE_BITSIZE (mode);
@@ -790,8 +767,8 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
            }
          if (i == len - unit)
            {
-             sprintf (name, ".rodata.str%d.%d", modesize / 8,
-                      (int) (align / 8));
+             sprintf (name, "%s.str%d.%d", prefix,
+                      modesize / 8, (int) (align / 8));
              flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS;
              return get_section (name, flags, NULL);
            }
@@ -818,9 +795,10 @@ mergeable_constant_section (enum machine_mode mode ATTRIBUTE_UNUSED,
       && align <= 256
       && (align & (align - 1)) == 0)
     {
-      char name[24];
+      const char *prefix = targetm.asm_out.mergeable_rodata_prefix;
+      char *name = (char *) alloca (strlen (prefix) + 30);
 
-      sprintf (name, ".rodata.cst%d", (int) (align / 8));
+      sprintf (name, "%s.cst%d", prefix, (int) (align / 8));
       flags |= (align / 8) | SECTION_MERGE;
       return get_section (name, flags, NULL);
     }
@@ -1266,7 +1244,7 @@ make_decl_rtl (tree decl)
 #endif
              nregs = hard_regno_nregs[reg_number][DECL_MODE (decl)];
              while (nregs > 0)
-               globalize_reg (reg_number + --nregs);
+               globalize_reg (decl, reg_number + --nregs);
            }
 
          /* As a register variable, it has no section.  */
@@ -1541,6 +1519,33 @@ notice_global_symbol (tree decl)
     }
 }
 
+/* If not using flag_reorder_blocks_and_partition, decide early whether the
+   current function goes into the cold section, so that targets can use
+   current_function_section during RTL expansion.  DECL describes the
+   function.  */
+
+void
+decide_function_section (tree decl)
+{
+  first_function_block_is_cold = false;
+
+  if (flag_reorder_blocks_and_partition)
+    /* We will decide in assemble_start_function.  */
+    return;
+
+ if (DECL_SECTION_NAME (decl))
+    {
+      struct cgraph_node *node = cgraph_get_node (current_function_decl);
+      /* Calls to function_section rely on first_function_block_is_cold
+        being accurate.  */
+      first_function_block_is_cold = (node
+                                     && node->frequency
+                                     == NODE_FREQUENCY_UNLIKELY_EXECUTED);
+    }
+
+  in_cold_section_p = first_function_block_is_cold;
+}
+
 /* Output assembler code for the constant pool of a function and associated
    with defining the name of the function.  DECL describes the function.
    NAME is the function's name.  For the constant pool, we use the current
@@ -1553,7 +1558,6 @@ assemble_start_function (tree decl, const char *fnname)
   char tmp_label[100];
   bool hot_label_written = false;
 
-  first_function_block_is_cold = false;
   if (flag_reorder_blocks_and_partition)
     {
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno);
@@ -1588,6 +1592,8 @@ assemble_start_function (tree decl, const char *fnname)
 
   if (flag_reorder_blocks_and_partition)
     {
+      first_function_block_is_cold = false;
+
       switch_to_section (unlikely_text_section ());
       assemble_align (DECL_ALIGN (decl));
       ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_label);
@@ -1604,17 +1610,9 @@ assemble_start_function (tree decl, const char *fnname)
          hot_label_written = true;
          first_function_block_is_cold = true;
        }
-    }
-  else if (DECL_SECTION_NAME (decl))
-    {
-      /* Calls to function_section rely on first_function_block_is_cold
-        being accurate.  */
-      first_function_block_is_cold
-        = (cgraph_node (current_function_decl)->frequency
-           == NODE_FREQUENCY_UNLIKELY_EXECUTED);
+      in_cold_section_p = first_function_block_is_cold;
     }
 
-  in_cold_section_p = first_function_block_is_cold;
 
   /* Switch to the correct text section for the start of the function.  */
 
@@ -1795,7 +1793,7 @@ emit_local (tree decl ATTRIBUTE_UNUSED,
 
 /* A noswitch_section_callback for bss_noswitch_section.  */
 
-#if defined ASM_OUTPUT_ALIGNED_BSS || defined ASM_OUTPUT_BSS
+#if defined ASM_OUTPUT_ALIGNED_BSS
 static bool
 emit_bss (tree decl ATTRIBUTE_UNUSED,
          const char *name ATTRIBUTE_UNUSED,
@@ -1805,9 +1803,6 @@ emit_bss (tree decl ATTRIBUTE_UNUSED,
 #if defined ASM_OUTPUT_ALIGNED_BSS
   ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl));
   return true;
-#else
-  ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded);
-  return false;
 #endif
 }
 #endif
@@ -2230,10 +2225,9 @@ mark_decl_referenced (tree decl)
         If we know a method will be emitted in other TU and no new
         functions can be marked reachable, just use the external
         definition.  */
-      struct cgraph_node *node = cgraph_node (decl);
+      struct cgraph_node *node = cgraph_get_create_node (decl);
       if (!DECL_EXTERNAL (decl)
-         && (!node->local.vtable_method || !cgraph_global_info_ready
-             || !node->local.finalized))
+         && !node->local.finalized)
        cgraph_mark_needed_node (node);
     }
   else if (TREE_CODE (decl) == VAR_DECL)
@@ -2397,7 +2391,7 @@ assemble_trampoline_template (void)
 
   initial_trampoline = gen_const_mem (BLKmode, symbol);
   set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
-  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
+  set_mem_size (initial_trampoline, TRAMPOLINE_SIZE);
 
   return initial_trampoline;
 }
@@ -3508,7 +3502,7 @@ force_const_mem (enum machine_mode mode, rtx x)
   void **slot;
 
   /* If we're not allowed to drop X into the constant pool, don't.  */
-  if (targetm.cannot_force_const_mem (x))
+  if (targetm.cannot_force_const_mem (mode, x))
     return NULL_RTX;
 
   /* Record that this function has used a constant pool entry.  */
@@ -4743,9 +4737,13 @@ output_constructor_regular_field (oc_local_state *local)
   unsigned int align2;
 
   if (local->index != NULL_TREE)
-    fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
-               * ((tree_low_cst (local->index, 0)
-                   - tree_low_cst (local->min_index, 0))));
+    {
+      double_int idx = double_int_sub (tree_to_double_int (local->index),
+                                      tree_to_double_int (local->min_index));
+      gcc_assert (double_int_fits_in_shwi_p (idx));
+      fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
+                 * idx.low);
+    }
   else if (local->field != NULL_TREE)
     fieldpos = int_byte_position (local->field);
   else
@@ -4792,13 +4790,8 @@ output_constructor_regular_field (oc_local_state *local)
             better be last.  */
          gcc_assert (!fieldsize || !DECL_CHAIN (local->field));
        }
-      else if (DECL_SIZE_UNIT (local->field))
-       {
-         /* ??? This can't be right.  If the decl size overflows
-            a host integer we will silently emit no data.  */
-         if (host_integerp (DECL_SIZE_UNIT (local->field), 1))
-           fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
-       }
+      else
+       fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
     }
   else
     fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
@@ -5071,14 +5064,12 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
       else if (TREE_CODE (local.type) == ARRAY_TYPE)
        local.index = ce->index;
 
-#ifdef ASM_COMMENT_START
       if (local.field && flag_verbose_asm)
        fprintf (asm_out_file, "%s %s:\n",
                 ASM_COMMENT_START,
                 DECL_NAME (local.field)
                 ? IDENTIFIER_POINTER (DECL_NAME (local.field))
                 : "<anonymous>");
-#endif
 
       /* Eliminate the marker that makes a cast not be an lvalue.  */
       if (local.val != NULL_TREE)
@@ -5838,7 +5829,7 @@ assemble_alias (tree decl, tree target)
 
   /* Allow aliases to aliases.  */
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    cgraph_node (decl)->alias = true;
+    cgraph_get_create_node (decl)->alias = true;
   else
     varpool_node (decl)->alias = true;
 
@@ -6004,7 +5995,7 @@ init_varasm_once (void)
   comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
                                       | SECTION_COMMON, emit_common);
 
-#if defined ASM_OUTPUT_ALIGNED_BSS || defined ASM_OUTPUT_BSS
+#if defined ASM_OUTPUT_ALIGNED_BSS
   bss_noswitch_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS,
                                               emit_bss);
 #endif
@@ -6189,12 +6180,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
        type = "progbits";
 
       format = ",@%s";
-#ifdef ASM_COMMENT_START
       /* On platforms that use "@" as the assembly comment character,
         use "%" instead.  */
       if (strcmp (ASM_COMMENT_START, "@") == 0)
        format = ",%%%s";
-#endif
       fprintf (asm_out_file, format, type);
 
       if (flags & SECTION_ENTSIZE)
@@ -6733,7 +6722,7 @@ default_binds_local_p_1 (const_tree exp, int shlib)
     }
   else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
     {
-      struct cgraph_node *node = cgraph_get_node_or_alias (exp);
+      struct cgraph_node *node = cgraph_get_node (exp);
       if (node
          && resolution_local_p (node->resolution))
        resolved_locally = true;
@@ -6798,7 +6787,7 @@ default_binds_local_p_1 (const_tree exp, int shlib)
    current module (shared library or executable), that is to binds_local_p.
    We use this fact to avoid need for another target hook and implement
    the logic using binds_local_p and just special cases where
-   decl_binds_to_current_def_p is stronger than binds local_p.  In particular
+   decl_binds_to_current_def_p is stronger than binds_local_p.  In particular
    the weak definitions (that can be overwritten at linktime by other
    definition from different object file) and when resolution info is available
    we simply use the knowledge passed to us by linker plugin.  */
@@ -6811,7 +6800,7 @@ decl_binds_to_current_def_p (tree decl)
   if (!targetm.binds_local_p (decl))
     return false;
   /* When resolution is available, just use it.  */
-  if (TREE_CODE (decl) == VAR_DECL && TREE_PUBLIC (decl)
+  if (TREE_CODE (decl) == VAR_DECL
       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
     {
       struct varpool_node *vnode = varpool_get_node (decl);
@@ -6819,9 +6808,9 @@ decl_binds_to_current_def_p (tree decl)
          && vnode->resolution != LDPR_UNKNOWN)
        return resolution_to_local_definition_p (vnode->resolution);
     }
-  else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl))
+  else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
-      struct cgraph_node *node = cgraph_get_node_or_alias (decl);
+      struct cgraph_node *node = cgraph_get_node (decl);
       if (node
          && node->resolution != LDPR_UNKNOWN)
        return resolution_to_local_definition_p (node->resolution);