bool first_function_block_is_cold;
-/* The following global variable indicates the label name to be put at
- the start of the first cold section within each function, when
- partitioning basic blocks into hot and cold sections. Used for
- debug info. */
-
-char *unlikely_section_label;
-
-/* The following global variable indicates the label name to be put at
- the start of the first hot section within each function, when
- partitioning basic blocks into hot and cold sections. Used for
- debug info. */
-
-char *hot_section_label;
-
-/* The following global variable indicates the label name to be put at
- the end of the last hot section within each function, when
- partitioning basic blocks into hot and cold sections. Used for
- debug info. */
-
-char *hot_section_end_label;
-
-/* The following global variable indicates the label name to be put at
- the end of the last cold section within each function, when
- partitioning basic blocks into hot and cold sections. Used for
- debug info.*/
-
-char *cold_section_end_label;
-
-/* The following global variable indicates the seciton name to be used
- for the current cold section, when partitiong hot and cold basic
- blocks into separate sections. */
-
-char *unlikely_text_section_name;
-
/* We give all constants their own alias set. Perhaps redundant with
MEM_READONLY_P, but pre-dates it. */
initialize_cold_section_name (void)
{
const char *name;
+ const char *stripped_name;
+ char *buffer;
int len;
- if (! unlikely_text_section_name)
+ if (cfun
+ && current_function_decl)
{
- if (DECL_SECTION_NAME (current_function_decl)
- && (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME
- (current_function_decl)),
- HOT_TEXT_SECTION_NAME) != 0)
- && (strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME
- (current_function_decl)),
- UNLIKELY_EXECUTED_TEXT_SECTION_NAME) != 0))
+ if (!cfun->unlikely_text_section_name)
{
- name = TREE_STRING_POINTER (DECL_SECTION_NAME
- (current_function_decl));
- len = strlen (name);
- unlikely_text_section_name = xmalloc (len + 10);
- sprintf (unlikely_text_section_name, "%s%s", name, "_unlikely");
+ if (flag_function_sections
+ && DECL_SECTION_NAME (current_function_decl))
+ {
+ name = xstrdup (TREE_STRING_POINTER (DECL_SECTION_NAME
+ (current_function_decl)));
+ stripped_name = targetm.strip_name_encoding (name);
+ len = strlen (stripped_name);
+ buffer = (char *) xmalloc (len + 10);
+ sprintf (buffer, "%s%s", stripped_name, "_unlikely");
+ cfun->unlikely_text_section_name = ggc_strdup (buffer);
+ free (buffer);
+ free ((char *) name);
+ }
+ else
+ cfun->unlikely_text_section_name =
+ UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
}
- else
- unlikely_text_section_name =
- xstrdup (UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
}
+ else
+ internal_error
+ ("initialize_cold_section_name called without valid current_function_decl.");
}
/* Tell assembler to switch to text section. */
void
unlikely_text_section (void)
{
- if (! unlikely_text_section_name)
- initialize_cold_section_name ();
+ if (cfun)
+ {
+ if (!cfun->unlikely_text_section_name)
+ initialize_cold_section_name ();
- if ((in_section != in_unlikely_executed_text)
- && (in_section != in_named
- || strcmp (in_named_name, unlikely_text_section_name) != 0))
+ if ((in_section != in_unlikely_executed_text)
+ && (in_section != in_named
+ || strcmp (in_named_name, cfun->unlikely_text_section_name) != 0))
+ {
+ named_section (NULL_TREE, cfun->unlikely_text_section_name, 0);
+ in_section = in_unlikely_executed_text;
+ last_text_section = in_unlikely_executed_text;
+ }
+ }
+ else
{
- named_section (NULL_TREE, unlikely_text_section_name, 0);
+ named_section (NULL_TREE, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
in_section = in_unlikely_executed_text;
last_text_section = in_unlikely_executed_text;
}
{
bool ret_val;
- ret_val = ((in_section == in_unlikely_executed_text)
- || (in_section == in_named
- && unlikely_text_section_name
- && strcmp (in_named_name, unlikely_text_section_name) == 0));
+ if (cfun)
+ {
+ ret_val = ((in_section == in_unlikely_executed_text)
+ || (in_section == in_named
+ && cfun->unlikely_text_section_name
+ && strcmp (in_named_name,
+ cfun->unlikely_text_section_name) == 0));
+ }
+ else
+ {
+ ret_val = ((in_section == in_unlikely_executed_text)
+ || (in_section == in_named
+ && strcmp (in_named_name,
+ UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0));
+ }
return ret_val;
}
name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
if (strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0
- && !unlikely_text_section_name)
- unlikely_text_section_name =
- xstrdup (UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
+ && cfun
+ && ! cfun->unlikely_text_section_name)
+ cfun->unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
flags = targetm.section_type_flags (decl, name, reloc);
/* Sanity check user variables for flag changes. Non-user
- section flag changes will abort in named_section_flags.
+ section flag changes will die in named_section_flags.
However, don't complain if SECTION_OVERRIDE is set.
We trust that the setter knows that it is safe to ignore
the default flags for this decl. */
void
function_section (tree decl)
{
- bool unlikely = false;
+ int reloc = 0;
if (first_function_block_is_cold)
- unlikely = true;
+ reloc = 1;
#ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
- targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl));
+ targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
#else
if (decl != NULL_TREE
- && DECL_SECTION_NAME (decl) != NULL_TREE)
+ && DECL_SECTION_NAME (decl) != NULL_TREE
+ && targetm.have_named_sections)
named_section (decl, (char *) 0, 0);
else
text_section ();
current_function_section (tree decl)
{
#ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
- bool unlikely = (in_unlikely_text_section ()
- || (last_text_section == in_unlikely_executed_text));
-
- targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl));
+ int reloc = 0;
+
+ if (in_unlikely_text_section ()
+ || last_text_section == in_unlikely_executed_text)
+ reloc = 1;
+
+ targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
#else
if (last_text_section == in_unlikely_executed_text)
unlikely_text_section ();
else if (last_text_section == in_text)
text_section ();
- else if (last_text_section == in_named)
+ else if (last_text_section == in_named
+ && targetm.have_named_sections)
named_section (NULL_TREE, last_text_section_name, 0);
else
function_section (decl);
{
const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
+ {
+ size_t len = strlen (name) + 3;
+ char* rname = alloca (len);
+
+ strcpy (rname, ".rodata");
+ strcat (rname, name + 5);
+ named_section_real (rname, SECTION_LINKONCE, decl);
+ return;
+ }
/* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo. */
- if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+ else if (DECL_ONE_ONLY (decl)
+ && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
{
size_t len = strlen (name) + 1;
char *rname = alloca (len);
error ("global register variable has initial value");
}
if (TREE_THIS_VOLATILE (decl))
- warning ("volatile register variables don%'t "
+ warning (0, "volatile register variables don%'t "
"work as you might wish");
/* If the user specified one of the eliminables registers here,
assemble_start_function (tree decl, const char *fnname)
{
int align;
+ char tmp_label[100];
bool hot_label_written = false;
- unlikely_text_section_name = NULL;
-
+ cfun->unlikely_text_section_name = NULL;
+
first_function_block_is_cold = false;
- hot_section_label = reconcat (hot_section_label, fnname, ".hot_section", NULL);
- unlikely_section_label = reconcat (unlikely_section_label,
- fnname, ".unlikely_section", NULL);
- hot_section_end_label = reconcat (hot_section_end_label,
- fnname, ".end", NULL);
- cold_section_end_label = reconcat (cold_section_end_label,
- fnname, ".end.cold", NULL);
+ if (flag_reorder_blocks_and_partition)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (tmp_label, "HOTB", const_labelno);
+ cfun->hot_section_label = ggc_strdup (tmp_label);
+ ASM_GENERATE_INTERNAL_LABEL (tmp_label, "COLDB", const_labelno);
+ cfun->cold_section_label = ggc_strdup (tmp_label);
+ ASM_GENERATE_INTERNAL_LABEL (tmp_label, "HOTE", const_labelno);
+ cfun->hot_section_end_label = ggc_strdup (tmp_label);
+ ASM_GENERATE_INTERNAL_LABEL (tmp_label, "COLDE", const_labelno);
+ cfun->cold_section_end_label = ggc_strdup (tmp_label);
+ const_labelno++;
+ }
+ else
+ {
+ cfun->hot_section_label = NULL;
+ cfun->cold_section_label = NULL;
+ cfun->hot_section_end_label = NULL;
+ cfun->cold_section_end_label = NULL;
+ }
/* The following code does not need preprocessing in the assembler. */
{
unlikely_text_section ();
assemble_align (FUNCTION_BOUNDARY);
- ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label);
+ ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_label);
if (BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
{
/* Since the function starts with a cold section, we need to
section label. */
text_section ();
assemble_align (FUNCTION_BOUNDARY);
- ASM_OUTPUT_LABEL (asm_out_file, hot_section_label);
+ ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
hot_label_written = true;
first_function_block_is_cold = true;
}
s[i] = (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)))[i];
s[len] = '\0';
- if (unlikely_text_section_name
- && (strcmp (s, unlikely_text_section_name) == 0))
+ if (cfun->unlikely_text_section_name
+ && (strcmp (s, cfun->unlikely_text_section_name) == 0))
first_function_block_is_cold = true;
}
last_text_section = no_section;
- in_section = no_section;
resolve_unique_section (decl, 0, flag_function_sections);
/* Switch to the correct text section for the start of the function. */
function_section (decl);
if (flag_reorder_blocks_and_partition
&& !hot_label_written)
- ASM_OUTPUT_LABEL (asm_out_file, hot_section_label);
+ ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
/* Tell assembler to move to target machine's alignment for functions. */
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
void
assemble_end_function (tree decl, const char *fnname)
{
- enum in_section save_text_section;
#ifdef ASM_DECLARE_FUNCTION_SIZE
ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
#endif
debug info.) */
if (flag_reorder_blocks_and_partition)
{
+ enum in_section save_text_section;
+
save_text_section = in_section;
unlikely_text_section ();
- ASM_OUTPUT_LABEL (asm_out_file, cold_section_end_label);
+ ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_end_label);
text_section ();
- ASM_OUTPUT_LABEL (asm_out_file, hot_section_end_label);
+ ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_end_label);
if (save_text_section == in_unlikely_executed_text)
unlikely_text_section ();
}
In particular, a.out format supports a maximum alignment of 4. */
if (align > MAX_OFILE_ALIGNMENT)
{
- warning ("%Jalignment of %qD is greater than maximum object "
+ warning (0, "%Jalignment of %qD is greater than maximum object "
"file alignment. Using %d", decl, decl,
MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
align = MAX_OFILE_ALIGNMENT;
#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
if ((unsigned HOST_WIDE_INT) DECL_ALIGN_UNIT (decl) > rounded)
- warning ("%Jrequested alignment for %qD is greater than "
+ warning (0, "%Jrequested alignment for %qD is greater than "
"implemented alignment of %d", decl, decl, rounded);
#endif
{
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- /* Extern inline functions don't become needed when referenced. */
- if (!DECL_EXTERNAL (decl))
- cgraph_mark_needed_node (cgraph_node (decl));
+ /* Extern inline functions don't become needed when referenced.
+ 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);
+ if (!DECL_EXTERNAL (decl)
+ && (!node->local.vtable_method || !cgraph_global_info_ready
+ || !node->local.finalized))
+ cgraph_mark_needed_node (node);
}
else if (TREE_CODE (decl) == VAR_DECL)
{
/* Assemble the integer constant X into an object of SIZE bytes. ALIGN is
the alignment of the integer in bits. Return 1 if we were able to output
- the constant, otherwise 0. If FORCE is nonzero, abort if we can't output
- the constant. */
+ the constant, otherwise 0. We must be able to output the constant,
+ if FORCE is nonzero. */
bool
assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
/* Given an expression EXP with a constant value,
reduce it to the sum of an assembler symbol and an integer.
Store them both in the structure *VALUE.
- Abort if EXP does not reduce. */
+ EXP must be reducible. */
struct addr_const GTY(())
{
case LABEL_DECL:
x = gen_rtx_MEM (FUNCTION_MODE,
- gen_rtx_LABEL_REF (VOIDmode, force_label_rtx (target)));
+ gen_rtx_LABEL_REF (Pmode, force_label_rtx (target)));
break;
case REAL_CST:
merge_weak (tree newdecl, tree olddecl)
{
if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
- return;
+ {
+ if (DECL_WEAK (newdecl) && SUPPORTS_WEAK)
+ {
+ tree *pwd;
+ /* We put the NEWDECL on the weak_decls list at some point
+ and OLDDECL as well. Keep just OLDDECL on the list. */
+ for (pwd = &weak_decls; *pwd; pwd = &TREE_CHAIN (*pwd))
+ if (TREE_VALUE (*pwd) == newdecl)
+ {
+ *pwd = TREE_CHAIN (*pwd);
+ break;
+ }
+ }
+ return;
+ }
if (DECL_WEAK (newdecl))
{
a weak symbol. */
else if (TREE_USED (olddecl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl)))
- warning ("%Jweak declaration of %qD after first use results "
+ warning (0, "%Jweak declaration of %qD after first use results "
"in unspecified behavior", newdecl, newdecl);
if (SUPPORTS_WEAK)
weak_decls = tree_cons (NULL, decl, weak_decls);
}
else
- warning ("%Jweak declaration of %qD not supported", decl, decl);
+ warning (0, "%Jweak declaration of %qD not supported", decl, decl);
mark_weak (decl);
}
ASM_WEAKEN_LABEL (asm_out_file, name);
#else
#ifdef ASM_OUTPUT_WEAK_ALIAS
- warning ("only weak aliases are supported in this configuration");
+ warning (0, "only weak aliases are supported in this configuration");
return;
#endif
#endif
of an alias. This requires that the decl have been defined. Aliases
that precede their definition have to be queued for later processing. */
-struct alias_pair GTY(())
+typedef struct alias_pair GTY(())
{
tree decl;
tree target;
-};
-typedef struct alias_pair *alias_pair;
+} alias_pair;
/* Define gc'd vector type. */
-DEF_VEC_GC_P(alias_pair);
+DEF_VEC_O(alias_pair);
+DEF_VEC_ALLOC_O(alias_pair,gc);
-static GTY(()) VEC(alias_pair) *alias_pairs;
+static GTY(()) VEC(alias_pair,gc) *alias_pairs;
/* Given an assembly name, find the decl it is associated with. At the
same time, mark it needed for cgraph. */
static void
do_assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
{
+ if (TREE_ASM_WRITTEN (decl))
+ return;
+
TREE_ASM_WRITTEN (decl) = 1;
TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
finish_aliases_1 (void)
{
unsigned i;
- alias_pair p;
+ alias_pair *p;
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
{
finish_aliases_2 (void)
{
unsigned i;
- alias_pair p;
+ alias_pair *p;
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
do_assemble_alias (p->decl, p->target);
- alias_pairs = NULL;
+ VEC_truncate (alias_pair, alias_pairs, 0);
}
/* Emit an assembler directive to make the symbol for DECL an alias to
do_assemble_alias (decl, target);
else
{
- alias_pair p;
-
- p = ggc_alloc (sizeof (struct alias_pair));
+ alias_pair *p = VEC_safe_push (alias_pair, gc, alias_pairs, NULL);
p->decl = decl;
p->target = target;
- VEC_safe_push (alias_pair, alias_pairs, p);
}
}
assemble_name (asm_out_file, name);
fprintf (asm_out_file, "\n");
#else
- warning ("visibility attribute not supported in this configuration; ignored");
+ warning (0, "visibility attribute not supported in this configuration; ignored");
#endif
}
flags = SECTION_CODE;
else if (decl && decl_readonly_section_1 (decl, reloc, shlib))
flags = 0;
- else if (unlikely_text_section_name
- && strcmp (name, unlikely_text_section_name) == 0)
+ else if (current_function_decl
+ && cfun
+ && cfun->unlikely_text_section_name
+ && strcmp (name, cfun->unlikely_text_section_name) == 0)
flags = SECTION_CODE;
+ else if (!decl
+ && (!current_function_decl || !cfun)
+ && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
+ flags = SECTION_CODE;
else
flags = SECTION_WRITE;
abbreviated form to switch back to it -- unless this section is
part of a COMDAT groups, in which case GAS requires the full
declaration every time. */
- if (!(HAVE_GAS_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
&& ! named_section_first_declaration (name))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
*f++ = 'S';
if (flags & SECTION_TLS)
*f++ = 'T';
- if (HAVE_GAS_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
*f = '\0';
if (flags & SECTION_ENTSIZE)
fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
- if (HAVE_GAS_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
fprintf (asm_out_file, ",%s,comdat",
lang_hooks.decls.comdat_group (decl));
}
void
default_unique_section_1 (tree decl, int reloc, int shlib)
{
- bool one_only = DECL_ONE_ONLY (decl);
+ /* We only need to use .gnu.linkonce if we don't have COMDAT groups. */
+ bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
const char *prefix, *name;
size_t nlen, plen;
char *string;