This adds the assembler_name member to cgraph_function_version_info to store the base assembler name for the function to be mangled. This is used in later patches for refactoring FMV mangling.
gcc/c/ChangeLog: * c-decl.cc (start_decl): Record assembler_name. (start_function): Record assembler_name. gcc/ChangeLog: * cgraph.cc (cgraph_node::record_function_versions): Record assembler_name. * cgraph.h (struct cgraph_function_version_info): Add assembler_name. gcc/cp/ChangeLog: * decl.cc (maybe_mark_function_versioned): Record assember_name. (start_decl): Record assembler_name. (start_preparsed_function): Record assembler_name. --- gcc/c/c-decl.cc | 20 ++++++++++++++++++++ gcc/cgraph.cc | 10 ++++++++-- gcc/cgraph.h | 3 +++ gcc/cp/decl.cc | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 0dcbae9b26f..daa19f360e6 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5762,6 +5762,16 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, && VAR_OR_FUNCTION_DECL_P (decl)) objc_check_global_decl (decl); + /* Store the base assembler name for mangling later. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && lookup_attribute ("target_clones", DECL_ATTRIBUTES (decl))) + { + cgraph_node *node = cgraph_node::get_create (decl); + if (!node->function_version ()) + node->insert_new_function_version (); + node->function_version ()->assembler_name = DECL_ASSEMBLER_NAME (decl); + } + /* Add this decl to the current scope. TEM may equal DECL or it may be a previous decl of the same name. */ if (do_push) @@ -10863,6 +10873,16 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, current_function_decl = pushdecl (decl1); + /* Store the base assembler name for mangling later. */ + if (TREE_CODE (decl1) == FUNCTION_DECL + && lookup_attribute ("target_clones", DECL_ATTRIBUTES (decl1))) + { + cgraph_node *node = cgraph_node::get_create (decl1); + if (!node->function_version ()) + node->insert_new_function_version (); + node->function_version ()->assembler_name = DECL_ASSEMBLER_NAME (decl1); + } + if (tree access = build_attr_access_from_parms (parms, false)) decl_attributes (¤t_function_decl, access, ATTR_FLAG_INTERNAL, old_decl); diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 1ea38d16e56..c2038be4671 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -252,10 +252,16 @@ cgraph_node::record_function_versions (tree decl1, tree decl2) decl2_v = decl2_node->function_version (); if (decl1_v == NULL) - decl1_v = decl1_node->insert_new_function_version (); + { + decl1_v = decl1_node->insert_new_function_version (); + decl1_v->assembler_name = DECL_ASSEMBLER_NAME (decl1); + } if (decl2_v == NULL) - decl2_v = decl2_node->insert_new_function_version (); + { + decl2_v = decl2_node->insert_new_function_version (); + decl2_v->assembler_name = DECL_ASSEMBLER_NAME (decl2); + } gcc_assert (decl1_v); gcc_assert (decl2_v); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 065fcc742e8..d9177364b7a 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -856,6 +856,9 @@ struct GTY((for_user)) cgraph_function_version_info { dispatcher. The dispatcher decl is an alias to the resolver function decl. */ tree dispatcher_resolver; + + /* The assmbly name of the function set before version mangling. */ + tree assembler_name; }; #define DEFCIFCODE(code, type, string) CIF_ ## code, diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 3b3b4481964..fdef98f8062 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -1273,6 +1273,12 @@ maybe_mark_function_versioned (tree decl) { if (!DECL_FUNCTION_VERSIONED (decl)) { + cgraph_node *node = cgraph_node::get_create (decl); + if (!node->function_version ()) + node->insert_new_function_version (); + if (!node->function_version ()->assembler_name) + node->function_version ()->assembler_name = DECL_ASSEMBLER_NAME (decl); + DECL_FUNCTION_VERSIONED (decl) = 1; /* If DECL_ASSEMBLER_NAME has already been set, re-mangle to include the version marker. */ @@ -6155,6 +6161,20 @@ start_decl (const cp_declarator *declarator, was_public = TREE_PUBLIC (decl); + /* Set the assembler string for any versioned function. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && (lookup_attribute (TARGET_HAS_FMV_TARGET_ATTRIBUTE ? "target" + : "target_version", + DECL_ATTRIBUTES (decl)) + || lookup_attribute ("target_clones", DECL_ATTRIBUTES (decl)))) + { + cgraph_node *node = cgraph_node::get_create (decl); + if (!node->function_version ()) + node->insert_new_function_version (); + if (!node->function_version ()->assembler_name) + node->function_version ()->assembler_name = DECL_ASSEMBLER_NAME (decl); + } + if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) && current_function_decl) { @@ -18743,6 +18763,20 @@ start_preparsed_function (tree decl1, tree attrs, int flags) if (!DECL_OMP_DECLARE_REDUCTION_P (decl1)) start_lambda_scope (decl1); + /* Set the assembler string for any versioned function. */ + if (TREE_CODE (decl1) == FUNCTION_DECL + && (lookup_attribute (TARGET_HAS_FMV_TARGET_ATTRIBUTE ? "target" + : "target_version", + DECL_ATTRIBUTES (decl1)) + || lookup_attribute ("target_clones", DECL_ATTRIBUTES (decl1)))) + { + cgraph_node *node = cgraph_node::get_create (decl1); + if (!node->function_version ()) + node->insert_new_function_version (); + if (!node->function_version ()->assembler_name) + node->function_version ()->assembler_name = DECL_ASSEMBLER_NAME (decl1); + } + return true; }