return true;
}
+/* Parse the tree in ARGS that contains the target_version attribute
+ information and update the global target options space. If LOC is nonnull,
+ report diagnostics against *LOC, otherwise remain silent. */
+
+bool
+loongarch_process_target_version_attr (tree args, tree fndecl)
+{
+ location_t loc = DECL_SOURCE_LOCATION (fndecl);
+
+ if (TREE_CODE (args) == TREE_LIST)
+ {
+ if (TREE_CHAIN (args))
+ {
+ if (loc)
+ error_at (loc, "attribute %<target_version%> "
+ "has multiple values");
+ return false;
+ }
+ args = TREE_VALUE (args);
+ }
+
+ if (!args || TREE_CODE (args) != STRING_CST)
+ {
+ if (loc)
+ error_at (loc, "attribute %<target_version%> argument not a string");
+ return false;
+ }
+
+ string_slice str = TREE_STRING_POINTER (args);
+
+ if (str == "default")
+ return true;
+
+ return loongarch_process_target_attr (args, fndecl);
+}
+
+/* Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P. This is used to
+ process attribute ((target_version ("..."))). */
+
+static bool
+loongarch_option_valid_version_attribute_p (tree fndecl, tree, tree args, int)
+{
+ struct cl_target_option cur_target;
+ bool ret;
+ tree new_target;
+ tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+
+ /* Save the current target options to restore at the end. */
+ cl_target_option_save (&cur_target, &global_options, &global_options_set);
+
+ /* If fndecl already has some target attributes applied to it, unpack
+ them so that we add this attribute on top of them, rather than
+ overwriting them. */
+ if (existing_target)
+ {
+ struct cl_target_option *existing_options
+ = TREE_TARGET_OPTION (existing_target);
+
+ if (existing_options)
+ cl_target_option_restore (&global_options, &global_options_set,
+ existing_options);
+ }
+ else
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (target_option_current_node));
+
+ ret = loongarch_process_target_version_attr (args, fndecl);
+
+ /* Set up any additional state. */
+ if (ret)
+ {
+ loongarch_option_override_internal (&la_target,
+ &global_options,
+ &global_options_set);
+ new_target = build_target_option_node (&global_options,
+ &global_options_set);
+ }
+ else
+ new_target = NULL;
+
+ if (fndecl && ret)
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
+
+ cl_target_option_restore (&global_options, &global_options_set, &cur_target);
+
+ return ret;
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
#undef TARGET_CAN_INLINE_P
#define TARGET_CAN_INLINE_P loongarch_can_inline_p
+#undef TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P
+#define TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P \
+ loongarch_option_valid_version_attribute_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-loongarch.h"