summaryrefslogtreecommitdiff
path: root/gcc/multiple_target.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2018-04-17 07:40:39 +0200
committerMartin Liska <marxin@gcc.gnu.org>2018-04-17 05:40:39 +0000
commit646cf2527541fb8928deee0d7eda9ca75a591328 (patch)
tree90085775e60ac8e9e866e3202e20f96c3a272e8a /gcc/multiple_target.c
parent42c884b130825022f3ff3621b6393eefa4cf36f6 (diff)
Make redirection only for target_clones: V3 (PR ipa/85329).
2018-04-17 Martin Liska <mliska@suse.cz> PR ipa/85329 * multiple_target.c (create_dispatcher_calls): Set apostrophes for target_clone error message. Make default implementation clone to be a local declaration. (separate_attrs): Add new argument and check for an empty string. (expand_target_clones): Handle it. (ipa_target_clone): Make redirection just for target_clones functions. 2018-04-17 Martin Liska <mliska@suse.cz> PR ipa/85329 * g++.dg/ext/pr85329-2.C: New test. * g++.dg/ext/pr85329.C: New test. * gcc.target/i386/mvc12.c: New test. From-SVN: r259428
Diffstat (limited to 'gcc/multiple_target.c')
-rw-r--r--gcc/multiple_target.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index b006a5ab6ec..a1fe09a5983 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -88,7 +88,7 @@ create_dispatcher_calls (struct cgraph_node *node)
if (!idecl)
{
error_at (DECL_SOURCE_LOCATION (node->decl),
- "default target_clones attribute was not set");
+ "default %<target_clones%> attribute was not set");
return;
}
@@ -161,10 +161,25 @@ create_dispatcher_calls (struct cgraph_node *node)
}
}
- TREE_PUBLIC (node->decl) = 0;
symtab->change_decl_assembler_name (node->decl,
clone_function_name (node->decl,
"default"));
+
+ /* FIXME: copy of cgraph_node::make_local that should be cleaned up
+ in next stage1. */
+ node->make_decl_local ();
+ node->set_section (NULL);
+ node->set_comdat_group (NULL);
+ node->externally_visible = false;
+ node->forced_by_abi = false;
+ node->set_section (NULL);
+ node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && !flag_incremental_link);
+ node->resolution = LDPR_PREVAILING_DEF_IRONLY;
+
+ DECL_ARTIFICIAL (node->decl) = 1;
+ node->force_output = true;
}
/* Return length of attribute names string,
@@ -216,26 +231,30 @@ get_attr_str (tree arglist, char *attr_str)
}
/* Return number of attributes separated by comma and put them into ARGS.
- If there is no DEFAULT attribute return -1. */
+ If there is no DEFAULT attribute return -1. If there is an empty
+ string in attribute return -2. */
static int
-separate_attrs (char *attr_str, char **attrs)
+separate_attrs (char *attr_str, char **attrs, int attrnum)
{
int i = 0;
- bool has_default = false;
+ int default_count = 0;
for (char *attr = strtok (attr_str, ",");
attr != NULL; attr = strtok (NULL, ","))
{
if (strcmp (attr, "default") == 0)
{
- has_default = true;
+ default_count++;
continue;
}
attrs[i++] = attr;
}
- if (!has_default)
+ if (default_count == 0)
return -1;
+ else if (i + default_count < attrnum)
+ return -2;
+
return i;
}
@@ -321,7 +340,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
{
warning_at (DECL_SOURCE_LOCATION (node->decl),
0,
- "single target_clones attribute is ignored");
+ "single %<target_clones%> attribute is ignored");
return false;
}
@@ -345,7 +364,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
int attrnum = get_attr_str (arglist, attr_str);
char **attrs = XNEWVEC (char *, attrnum);
- attrnum = separate_attrs (attr_str, attrs);
+ attrnum = separate_attrs (attr_str, attrs, attrnum);
if (attrnum == -1)
{
error_at (DECL_SOURCE_LOCATION (node->decl),
@@ -354,6 +373,14 @@ expand_target_clones (struct cgraph_node *node, bool definition)
XDELETEVEC (attr_str);
return false;
}
+ else if (attrnum == -2)
+ {
+ error_at (DECL_SOURCE_LOCATION (node->decl),
+ "an empty string cannot be in %<target_clones%> attribute");
+ XDELETEVEC (attrs);
+ XDELETEVEC (attr_str);
+ return false;
+ }
cgraph_function_version_info *decl1_v = NULL;
cgraph_function_version_info *decl2_v = NULL;
@@ -427,14 +454,14 @@ static unsigned int
ipa_target_clone (void)
{
struct cgraph_node *node;
+ auto_vec<cgraph_node *> to_dispatch;
- bool target_clone_pass = false;
FOR_EACH_FUNCTION (node)
- target_clone_pass |= expand_target_clones (node, node->definition);
+ if (expand_target_clones (node, node->definition))
+ to_dispatch.safe_push (node);
- if (target_clone_pass)
- FOR_EACH_FUNCTION (node)
- create_dispatcher_calls (node);
+ for (unsigned i = 0; i < to_dispatch.length (); i++)
+ create_dispatcher_calls (to_dispatch[i]);
return 0;
}