function. */
bool
-aarch64_same_function_versions (string_slice str1, string_slice str2)
+aarch64_same_function_versions (string_slice old_str, const_tree,
+ string_slice new_str, const_tree)
{
enum aarch_parse_opt_result parse_res;
- aarch64_fmv_feature_mask feature_mask1;
- aarch64_fmv_feature_mask feature_mask2;
- parse_res = aarch64_parse_fmv_features (str1, NULL,
- &feature_mask1, NULL);
+ aarch64_fmv_feature_mask old_feature_mask;
+ aarch64_fmv_feature_mask new_feature_mask;
+
+ parse_res = aarch64_parse_fmv_features (old_str, NULL, &old_feature_mask,
+ NULL);
gcc_assert (parse_res == AARCH_PARSE_OK);
- parse_res = aarch64_parse_fmv_features (str2, NULL,
- &feature_mask2, NULL);
+
+ parse_res = aarch64_parse_fmv_features (new_str, NULL, &new_feature_mask,
+ NULL);
gcc_assert (parse_res == AARCH_PARSE_OK);
- return feature_mask1 == feature_mask2;
+ return old_feature_mask == new_feature_mask;
}
/* Implement TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P. Use an opt-out
This assumes that FN1 and FN2 have the same signature. */
bool
-loongarch_option_same_function_versions (string_slice str1, string_slice str2)
+loongarch_option_same_function_versions (string_slice str1, const_tree,
+ string_slice str2, const_tree)
{
loongarch_fmv_feature_mask feature_mask1;
loongarch_fmv_feature_mask feature_mask2;
version. */
bool
-riscv_same_function_versions (string_slice v1, string_slice v2)
+riscv_same_function_versions (string_slice v1, const_tree, string_slice v2,
+ const_tree)
{
struct riscv_feature_bits mask1, mask2;
int prio1, prio2;
@code{TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE}
@end deftypefn
-@deftypefn {Target Hook} bool TARGET_OPTION_SAME_FUNCTION_VERSIONS (string_slice @var{fn1}, string_slice @var{fn2})
+@deftypefn {Target Hook} bool TARGET_OPTION_SAME_FUNCTION_VERSIONS (string_slice @var{fn1}, const_tree @var{decl1}, string_slice @var{fn2}, const_tree @var{decl2})
This target hook returns @code{true} if the target/target-version strings
@var{fn1} and @var{fn2} imply the same function version.
+
+If @var{decl1} and @var{decl2} are non @code{NULL} then @var{fn1} and
+@var{fn2} are from an earlier and a later declaration respectively, and the
+hook diagnoses any version string incompatibility for these decls.
+If the version strings are incompatible and the declarations can not be
+merged, then hook emits an error.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_OPTION_FUNCTIONS_B_RESOLVABLE_FROM_A (tree @var{decl_a}, tree @var{decl_v}, tree @var{base})
}
bool
-hook_stringslice_stringslice_unreachable (string_slice, string_slice)
+hook_stringslice_consttree_stringslice_consttree_unreachable (string_slice,
+ const_tree,
+ string_slice,
+ const_tree)
{
gcc_unreachable ();
}
unsigned HOST_WIDE_INT);
extern bool hook_stringslice_locationtptr_true (string_slice, location_t *);
-extern bool hook_stringslice_stringslice_unreachable (string_slice, string_slice);
+extern bool hook_stringslice_consttree_stringslice_consttree_unreachable (string_slice, const_tree, string_slice, const_tree);
#endif
void, (void),
hook_void_void)
-/* This function returns true if FN1 and FN2 define the same version of a
- function. */
+/* This function returns true if FN1 and FN2 define the same version
+ of a function.
+ If DECL1 and DECL2 is not-null then emit a diagnostic if the versions do
+ imply the same version, but are not mergeable. */
DEFHOOK
(same_function_versions,
"This target hook returns @code{true} if the target/target-version strings\n\
-@var{fn1} and @var{fn2} imply the same function version.",
- bool, (string_slice fn1, string_slice fn2),
- hook_stringslice_stringslice_unreachable)
+@var{fn1} and @var{fn2} imply the same function version.\n\
+\n\
+If @var{decl1} and @var{decl2} are non @code{NULL} then @var{fn1} and\n\
+@var{fn2} are from an earlier and a later declaration respectively, and the\n\
+hook diagnoses any version string incompatibility for these decls.\n\
+If the version strings are incompatible and the declarations can not be\n\
+merged, then hook emits an error.",
+ bool, (string_slice fn1, const_tree decl1, string_slice fn2, const_tree decl2),
+ hook_stringslice_consttree_stringslice_consttree_unreachable)
/* Checks if we can be certain that function DECL_A could resolve DECL_B. */
DEFHOOK
for (string_slice v1 : fn1_versions)
{
for (string_slice v2 : fn2_versions)
- if (targetm.target_option.same_function_versions (v1, v2))
+ if (targetm.target_option.same_function_versions
+ (v1, NULL_TREE, v2, NULL_TREE))
return false;
}
return true;
if (!v2.is_valid ())
v2 = "default";
for (string_slice v1 : fn1_versions)
- if (targetm.target_option.same_function_versions (v1, v2))
+ if (targetm.target_option.same_function_versions
+ (v1, NULL_TREE, v2, NULL_TREE))
return false;
return true;
}
if (!v2.is_valid ())
v2 = "default";
- if (targetm.target_option.same_function_versions (v1, v2))
+ if (targetm.target_option.same_function_versions (v1, NULL_TREE,
+ v2, NULL_TREE))
return false;
return true;
the two sets of target_clones imply the same set of versions. */
if (old_target_clones_attr && new_target_clones_attr)
{
- auto_vec<string_slice> fn1_versions = get_clone_versions (old_decl);
- auto_vec<string_slice> fn2_versions = get_clone_versions (new_decl);
+ auto_vec<string_slice> old_versions = get_clone_versions (old_decl);
+ auto_vec<string_slice> new_versions = get_clone_versions (new_decl);
bool mergeable = true;
- if (fn1_versions.length () != fn2_versions.length ())
+ if (old_versions.length () != new_versions.length ())
mergeable = false;
/* Check both inclusion directions. */
- for (auto fn1v : fn1_versions)
+ for (auto oldv: old_versions)
{
bool matched = false;
- for (auto fn2v : fn2_versions)
- if (targetm.target_option.same_function_versions (fn1v, fn2v))
+ for (auto newv: new_versions)
+ if (targetm.target_option.same_function_versions (oldv, old_decl,
+ newv, new_decl))
matched = true;
if (!matched)
mergeable = false;
}
- for (auto fn2v : fn2_versions)
+ for (auto newv: new_versions)
{
bool matched = false;
- for (auto fn1v : fn1_versions)
- if (targetm.target_option.same_function_versions (fn1v, fn2v))
+ for (auto oldv: old_versions)
+ if (targetm.target_option.same_function_versions (oldv, old_decl,
+ newv, new_decl))
matched = true;
if (!matched)
mergeable = false;
return true;
}
- /* The only remaining case is two target_version annotated decls. Must
- be mergeable as otherwise are distinct. */
- return false;
+ /* The only remaining case is two target_version annotated decls. */
+ return !targetm.target_option.same_function_versions
+ (old_target_attr, old_decl, new_target_attr, new_decl);
}
void