The RISC-V psABI[1] says a function using a standard calling convention variant has to append an extra ABI tag to its mangled name, following the "ABI tags" rule of the Itanium C++ ABI. The only variant listed so far is the fixed-length vector calling convention, whose tag is riscv_vls_cc_<ABI_VLEN>:
```c __attribute__((riscv_vls_cc(128))) void foo(); ``` now mangles as _Z3fooB16riscv_vls_cc_128v. The C++ mangler cannot know about target attributes, so we adds a target hook, TARGET_CXX_IMPLICIT_ABI_TAGS, that hands back extra tags for a decl. NOTE: I tried to not adding the new hook by attaching abi_tag attribute, however I tried to doing that on TARGET_INSERT_ATTRIBUTES and doing some hack way on TARGET_ATTRIBUTE_TABLE during adding calling convention attribute, but both are no work well. [1] "Name Mangling for Standard Calling Convention Variant" in https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc gcc/ChangeLog: * target.def (TARGET_CXX_IMPLICIT_ABI_TAGS): New hook. * doc/tm.texi.in (TARGET_CXX_IMPLICIT_ABI_TAGS): Document it. * doc/tm.texi: Regenerate. * config/riscv/riscv.cc (riscv_get_vls_cc_attr): Let CHECK_ONLY suppress the diagnostic only, not the validity test. (riscv_lookup_vls_cc_attribute): New function. (riscv_vls_cc_function_abi): Use it, and take the arguments from the attribute that was found. (riscv_cxx_implicit_abi_tags): New function. (TARGET_CXX_IMPLICIT_ABI_TAGS): Define. gcc/cp/ChangeLog: * mangle.cc (write_unqualified_name): Write the ABI tags the target asks for. gcc/testsuite/ChangeLog: * g++.target/riscv/mangle-vls-cc.C: New test. --- gcc/config/riscv/riscv.cc | 64 +++++++++++++++---- gcc/cp/mangle.cc | 7 ++ gcc/doc/tm.texi | 8 +++ gcc/doc/tm.texi.in | 2 + gcc/target.def | 10 +++ .../g++.target/riscv/mangle-vls-cc.C | 55 ++++++++++++++++ 6 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.target/riscv/mangle-vls-cc.C diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b9e6d2fa42c..00c5e62d6b7 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -8135,39 +8135,48 @@ riscv_get_vls_cc_attr (const_tree args, bool check_only = false) abi_vlen = TREE_INT_CST_LOW (vlen_arg); } - if (!riscv_valid_abi_vlen_vls_cc_p (abi_vlen) && !check_only) + if (!riscv_valid_abi_vlen_vls_cc_p (abi_vlen)) { - error_at (input_location, - "unsupported %<ABI_VLEN%> value %d for %qs attribute; " - "%<ABI_VLEN%> must be in the range [32, 16384] and must be " - "a power of 2", - abi_vlen, "riscv_vls_cc"); + if (!check_only) + error_at (input_location, + "unsupported %<ABI_VLEN%> value %d for %qs attribute; " + "%<ABI_VLEN%> must be in the range [32, 16384] and must be " + "a power of 2", + abi_vlen, "riscv_vls_cc"); return RISCV_CC_UNKNOWN; } return riscv_get_riscv_cc_by_abi_vlen (abi_vlen); } +/* Return the vls_cc attribute in ATTRS, either spelling, or NULL_TREE. */ + +static tree +riscv_lookup_vls_cc_attribute (tree attrs) +{ + tree attr = lookup_attribute ("vls_cc", attrs); + if (!attr) + attr = lookup_attribute ("riscv_vls_cc", attrs); + return attr; +} + /* Return true if FUNC is a riscv_vector_cc function. For more details please reference the below link. https://github.com/riscv-non-isa/riscv-c-api-doc/pull/67 */ static riscv_cc riscv_vls_cc_function_abi (const_tree fntype, bool check_only) { - tree attr = TYPE_ATTRIBUTES (fntype); - bool vls_cc_p = lookup_attribute ("vls_cc", attr) != NULL_TREE - || lookup_attribute ("riscv_vls_cc", attr) != NULL_TREE; + tree attr = riscv_lookup_vls_cc_attribute (TYPE_ATTRIBUTES (fntype)); - if (!vls_cc_p) + if (!attr) return RISCV_CC_UNKNOWN; if (!TARGET_VECTOR && !check_only) error_at (input_location, "function attribute %qs requires the vector ISA extension", "riscv_vls_cc"); - tree args = TREE_VALUE (attr); - return riscv_get_vls_cc_attr (args); + return riscv_get_vls_cc_attr (args, check_only); } /* Implementation of TARGET_FNTYPE_ABI, but one extra parameter `check_only` @@ -8203,6 +8212,34 @@ riscv_fntype_abi (const_tree fntype) return riscv_fntype_abi_1 (fntype, /* check_only */true); } +/* Implement TARGET_CXX_IMPLICIT_ABI_TAGS. The psABI tags a function using the + fixed-length vector calling convention with riscv_vls_cc_<ABI_VLEN>. */ + +static tree +riscv_cxx_implicit_abi_tags (const_tree decl) +{ + if (TREE_CODE (decl) != FUNCTION_DECL) + return NULL_TREE; + + /* On a template the attribute only reaches the type at instantiation. */ + tree attr + = riscv_lookup_vls_cc_attribute (TYPE_ATTRIBUTES (TREE_TYPE (decl))); + if (!attr) + attr = riscv_lookup_vls_cc_attribute (DECL_ATTRIBUTES (decl)); + if (!attr) + return NULL_TREE; + + riscv_cc cc = riscv_get_vls_cc_attr (TREE_VALUE (attr), + /* check_only */ true); + if (!riscv_vls_cc_p (cc)) + return NULL_TREE; + + char tag[sizeof ("riscv_vls_cc_") + 3 * sizeof (unsigned int)]; + int len = snprintf (tag, sizeof (tag), "riscv_vls_cc_%u", + riscv_get_cc_abi_vlen (cc)); + return build_tree_list (NULL_TREE, build_string (len + 1, tag)); +} + /* Handle an attribute requiring a FUNCTION_DECL; arguments as in struct attribute_spec.handler. */ static tree @@ -17164,6 +17201,9 @@ riscv_memtag_tag_bitsize () #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE riscv_mangle_type +#undef TARGET_CXX_IMPLICIT_ABI_TAGS +#define TARGET_CXX_IMPLICIT_ABI_TAGS riscv_cxx_implicit_abi_tags + #undef TARGET_SCALAR_MODE_SUPPORTED_P #define TARGET_SCALAR_MODE_SUPPORTED_P riscv_scalar_mode_supported_p diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index bdd62611c5b..6436a5b4760 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -1668,6 +1668,13 @@ write_unqualified_name (tree decl) if (!abi_check (11)) tags = chainon (mtags, tags); } + /* A template-id is mangled from its template, so ask about the pattern. */ + tree tdecl = decl; + if (TREE_CODE (tdecl) == TEMPLATE_DECL) + tdecl = DECL_TEMPLATE_RESULT (tdecl); + if (tdecl) + if (tree itags = targetm.cxx.implicit_abi_tags (tdecl)) + tags = chainon (itags, tags); write_abi_tags (tags); } diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2613b95775b..4a800907657 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11367,6 +11367,14 @@ visibility or perform any other required target modifications). Return target-specific mangling context of @var{decl} or @code{NULL_TREE}. @end deftypefn +@deftypefn {Target Hook} tree TARGET_CXX_IMPLICIT_ABI_TAGS (const_tree @var{decl}) +Return a freshly built @code{TREE_LIST} of ABI tags that the C++ mangler +must add to the name of @var{decl} on top of the tags from its +@code{abi_tag} attribute, or @code{NULL_TREE}. Each @code{TREE_VALUE} is a +@code{STRING_CST} holding one tag. A target needs this when its psABI asks +for an ABI tag on functions that use a calling convention variant. +@end deftypefn + @node D Language and ABI @section D ABI parameters @cindex parameters, d abi diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 0d2a76ec6b0..e565fd74ef5 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7298,6 +7298,8 @@ floating-point support; they are not included in this mechanism. @hook TARGET_CXX_DECL_MANGLING_CONTEXT +@hook TARGET_CXX_IMPLICIT_ABI_TAGS + @node D Language and ABI @section D ABI parameters @cindex parameters, d abi diff --git a/gcc/target.def b/gcc/target.def index bf2825e991d..b896918811e 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -6798,6 +6798,16 @@ DEFHOOK tree, (const_tree decl), hook_tree_const_tree_null) +DEFHOOK +(implicit_abi_tags, + "Return a freshly built @code{TREE_LIST} of ABI tags that the C++ mangler\n\ +must add to the name of @var{decl} on top of the tags from its\n\ +@code{abi_tag} attribute, or @code{NULL_TREE}. Each @code{TREE_VALUE} is a\n\ +@code{STRING_CST} holding one tag. A target needs this when its psABI asks\n\ +for an ABI tag on functions that use a calling convention variant.", + tree, (const_tree decl), + hook_tree_const_tree_null) + HOOK_VECTOR_END (cxx) /* Functions and data for emulated TLS support. */ diff --git a/gcc/testsuite/g++.target/riscv/mangle-vls-cc.C b/gcc/testsuite/g++.target/riscv/mangle-vls-cc.C new file mode 100644 index 00000000000..1dda4266a0c --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mangle-vls-cc.C @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d" } */ + +/* The psABI asks a function using a standard calling convention variant to + append an ABI tag to its mangled name. */ + +__attribute__((riscv_vls_cc)) void default_vls_cc () {} + +__attribute__((riscv_vls_cc(32))) void vlen_32 () {} + +__attribute__((riscv_vls_cc(128))) void vlen_128 () {} + +__attribute__((riscv_vls_cc(16384))) void vlen_16384 () {} + +namespace v64 { __attribute__((riscv_vls_cc(64))) void f () {} } +namespace v512 { __attribute__((riscv_vls_cc(512))) void f () {} } + +typedef void vls_fn_t (void) __attribute__((riscv_vls_cc(256))); +vls_fn_t from_typedef; +void from_typedef () {} + +__attribute__((abi_tag("user"))) __attribute__((riscv_vls_cc(128))) +void tagged () {} + +__attribute__((abi_tag("user", "abc"), riscv_vls_cc(128))) +void tagged2 () {} + +namespace ns { + struct S { + __attribute__((riscv_vls_cc(128))) void member () {} + }; + void instantiate () { S ().member (); } +} + +template <typename T> __attribute__((riscv_vls_cc(128))) void tpl (T) {} +template void tpl<int> (int); + +/* The VLA vector calling convention variant has no ABI tag. */ +__attribute__((riscv_vector_cc)) void vector_cc () {} + +void plain () {} + +/* { dg-final { scan-assembler "_Z14default_vls_ccB16riscv_vls_cc_128v:" } } */ +/* { dg-final { scan-assembler "_Z7vlen_32B15riscv_vls_cc_32v:" } } */ +/* { dg-final { scan-assembler "_Z8vlen_128B16riscv_vls_cc_128v:" } } */ +/* { dg-final { scan-assembler "_Z10vlen_16384B18riscv_vls_cc_16384v:" } } */ +/* { dg-final { scan-assembler "_ZN3v641fB15riscv_vls_cc_64Ev:" } } */ +/* { dg-final { scan-assembler "_ZN4v5121fB16riscv_vls_cc_512Ev:" } } */ +/* { dg-final { scan-assembler "_Z12from_typedefB16riscv_vls_cc_256v:" } } */ +/* { dg-final { scan-assembler "_Z6taggedB16riscv_vls_cc_128B4userv:" } } */ +/* { dg-final { scan-assembler "_Z7tagged2B3abcB16riscv_vls_cc_128B4userv:" } } */ +/* { dg-final { scan-assembler "_ZN2ns1S6memberB16riscv_vls_cc_128Ev:" } } */ +/* { dg-final { scan-assembler "_Z3tplB16riscv_vls_cc_128IiEvT_:" } } */ +/* { dg-final { scan-assembler "_Z9vector_ccv:" } } */ +/* { dg-final { scan-assembler "_Z5plainv:" } } */ -- 2.54.0
