This hook is used to get the dispatcher function for a set of function
versions. This function is copied from aarch64.
gcc/ChangeLog:
* config/loongarch/loongarch.cc
(loongarch_get_function_versions_dispatcher): New function.
(TARGET_GET_FUNCTION_VERSIONS_DISPATCHER): Define.
Change-Id: If2e36db7669a5f2076d15815d95d9c9dec6cb56f
---
gcc/config/loongarch/loongarch.cc | 77 +++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index 4382deb9e79..8b8187c37db 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -11396,6 +11396,79 @@ loongarch_option_valid_version_attribute_p (tree
fndecl, tree, tree args, int)
return ret;
}
+/* Make a dispatcher declaration for the multi-versioned function DECL.
+ Calls to DECL function will be replaced with calls to the dispatcher
+ by the front-end. Returns the decl of the dispatcher function. */
+
+tree
+loongarch_get_function_versions_dispatcher (void *decl)
+{
+ tree fn = (tree) decl;
+ struct cgraph_node *node = NULL;
+ struct cgraph_node *default_node = NULL;
+ struct cgraph_function_version_info *node_v = NULL;
+
+ tree dispatch_decl = NULL;
+
+ struct cgraph_function_version_info *default_version_info = NULL;
+
+ gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn));
+
+ node = cgraph_node::get (fn);
+ gcc_assert (node != NULL);
+
+ node_v = node->function_version ();
+ gcc_assert (node_v != NULL);
+
+ if (node_v->dispatcher_resolver != NULL)
+ return node_v->dispatcher_resolver;
+
+ /* The default node is always the beginning of the chain. */
+ default_version_info = node_v;
+ while (default_version_info->prev)
+ default_version_info = default_version_info->prev;
+ default_node = default_version_info->this_node;
+
+ /* If there is no default node, just return NULL. */
+ if (!is_function_default_version (default_node->decl))
+ return NULL;
+
+ if (targetm.has_ifunc_p ())
+ {
+ struct cgraph_function_version_info *it_v = NULL;
+ struct cgraph_node *dispatcher_node = NULL;
+ struct cgraph_function_version_info *dispatcher_version_info = NULL;
+
+ /* Right now, the dispatching is done via ifunc. */
+ dispatch_decl = make_dispatcher_decl (default_node->decl);
+ TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn);
+
+ dispatcher_node = cgraph_node::get_create (dispatch_decl);
+ gcc_assert (dispatcher_node != NULL);
+ dispatcher_node->dispatcher_function = 1;
+ dispatcher_version_info
+ = dispatcher_node->insert_new_function_version ();
+ dispatcher_version_info->next = default_version_info;
+ dispatcher_node->definition = 1;
+
+ /* Set the dispatcher for all the versions. */
+ it_v = default_version_info;
+ while (it_v != NULL)
+ {
+ it_v->dispatcher_resolver = dispatch_decl;
+ it_v = it_v->next;
+ }
+ }
+ else
+ {
+ error_at (DECL_SOURCE_LOCATION (default_node->decl),
+ "multiversioning needs %<ifunc%> which is not supported "
+ "on this target");
+ }
+
+ return dispatch_decl;
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -11687,6 +11760,10 @@ loongarch_option_valid_version_attribute_p (tree
fndecl, tree, tree args, int)
#define TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P \
loongarch_option_valid_version_attribute_p
+#undef TARGET_GET_FUNCTION_VERSIONS_DISPATCHER
+#define TARGET_GET_FUNCTION_VERSIONS_DISPATCHER \
+ loongarch_get_function_versions_dispatcher
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-loongarch.h"
--
2.34.1