https://github.com/kito-cheng updated https://github.com/llvm/llvm-project/pull/217249
>From 012b8f3c921b122c7812c759d6b2e7d769ef9cc3 Mon Sep 17 00:00:00 2001 From: Kito Cheng <[email protected]> Date: Thu, 13 Aug 2026 21:20:58 +0800 Subject: [PATCH 1/5] [Clang][RISCV] Mangle the ABI tag of a standard calling convention variant The psABI 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>: `__attribute__((riscv_vls_cc(128))) void foo();` now mangles as `_Z3fooB16riscv_vls_cc_128v`. The tag comes from the calling convention of the function type, so it also covers a convention picked up from a typedef. It is emitted like an explicit abi_tag attribute: sorted and deduplicated together with the explicit tags, and never dropped as a derived tag. Note the example in the psABI writes the tag length as B12, which does not match the 16 characters of "riscv_vls_cc_128". See "Name Mangling for Standard Calling Convention Variant" in https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc Assisted-by: Opus. --- clang/lib/AST/ItaniumMangle.cpp | 39 +++++++++ .../riscv-vector-callingconv-llvm-ir.cpp | 80 +++++++++---------- clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp | 55 +++++++++++++ 3 files changed, 134 insertions(+), 40 deletions(-) create mode 100644 clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index f8e6b898be250..d20964a969f64 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -213,6 +213,40 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { /// @} }; +/// Return the ABI tag that a function using a standard calling convention +/// variant has to append to its name, or an empty string if the function does +/// not use such a variant. +static StringRef getCallingConvAbiTag(const NamedDecl *ND) { + const auto *FD = dyn_cast<FunctionDecl>(ND); + if (!FD) + return {}; + + const auto *FT = FD->getType()->getAs<FunctionType>(); + if (!FT) + return {}; + + switch (FT->getCallConv()) { +#define CC_VLS_CASE(ABI_VLEN) \ + case CC_RISCVVLSCall_##ABI_VLEN: \ + return "riscv_vls_cc_" #ABI_VLEN; + CC_VLS_CASE(32) + CC_VLS_CASE(64) + CC_VLS_CASE(128) + CC_VLS_CASE(256) + CC_VLS_CASE(512) + CC_VLS_CASE(1024) + CC_VLS_CASE(2048) + CC_VLS_CASE(4096) + CC_VLS_CASE(8192) + CC_VLS_CASE(16384) + CC_VLS_CASE(32768) + CC_VLS_CASE(65536) +#undef CC_VLS_CASE + default: + return {}; + } +} + /// Manage the mangling of a single name. class CXXNameMangler { ItaniumMangleContextImpl &Context; @@ -316,6 +350,11 @@ class CXXNameMangler { llvm::append_range(TagList, AbiTag->tags()); } + if (StringRef CCTag = getCallingConvAbiTag(ND); !CCTag.empty()) { + UsedAbiTags.push_back(CCTag); + TagList.push_back(CCTag); + } + llvm::append_range(UsedAbiTags, AdditionalAbiTags); llvm::append_range(TagList, AdditionalAbiTags); diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp index 233c83020ab5e..15fafa92c1162 100644 --- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp @@ -38,28 +38,28 @@ vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { // CHECK-LLVM: define dso_local void @_Z14test_vls_no_ccDv4_i(i128 noundef %arg.coerce) void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z25test_vls_default_abi_vlenDv4_i(<vscale x 2 x i32> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z25test_vls_default_abi_vlenB16riscv_vls_cc_128Dv4_i(<vscale x 2 x i32> noundef %arg.coerce) [[riscv::vls_cc]] void test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z45test_vls_default_abi_vlen_unsupported_featureDv8_DF16_(<vscale x 8 x i8> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z45test_vls_default_abi_vlen_unsupported_featureB16riscv_vls_cc_128Dv8_DF16_(<vscale x 8 x i8> noundef %arg.coerce) [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z32test_vls_default_abi_vlen_bfloatDv8_DF16b(<vscale x 8 x i8> noundef %arg.coerce) -// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(128) void @_Z32test_vls_default_abi_vlen_bfloatDv8_DF16b(<vscale x 4 x bfloat> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z32test_vls_default_abi_vlen_bfloatB16riscv_vls_cc_128Dv8_DF16b(<vscale x 8 x i8> noundef %arg.coerce) +// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(128) void @_Z32test_vls_default_abi_vlen_bfloatB16riscv_vls_cc_128Dv8_DF16b(<vscale x 4 x bfloat> noundef %arg.coerce) [[riscv::vls_cc]] void test_vls_default_abi_vlen_bfloat(__attribute__((vector_size(16))) __bf16 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 2 x float> noundef %arg.coerce) -// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xDv4_f(<vscale x 8 x i8> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xB16riscv_vls_cc_128Dv4_f(<vscale x 2 x float> noundef %arg.coerce) +// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z52test_vls_default_abi_vlen_unsupported_feature_zve32xB16riscv_vls_cc_128Dv4_f(<vscale x 8 x i8> noundef %arg.coerce) [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z55test_vls_default_abi_vlen_unsupported_feature_no_zve64xDv2_m(<vscale x 1 x i64> noundef %arg.coerce) -// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z55test_vls_default_abi_vlen_unsupported_feature_no_zve64xDv2_m(<vscale x 8 x i8> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z55test_vls_default_abi_vlen_unsupported_feature_no_zve64xB16riscv_vls_cc_128Dv2_m(<vscale x 1 x i64> noundef %arg.coerce) +// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @_Z55test_vls_default_abi_vlen_unsupported_feature_no_zve64xB16riscv_vls_cc_128Dv2_m(<vscale x 8 x i8> noundef %arg.coerce) [[riscv::vls_cc]] void test_vls_default_abi_vlen_unsupported_feature_no_zve64x(__attribute__((vector_size(16))) uint64_t arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z21test_vls_256_abi_vlenDv4_i(<vscale x 1 x i32> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z21test_vls_256_abi_vlenB16riscv_vls_cc_256Dv4_i(<vscale x 1 x i32> noundef %arg.coerce) [[riscv::vls_cc(256)]] void test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @_Z22test_vls_least_elementDv2_i(<vscale x 1 x i32> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @_Z22test_vls_least_elementB17riscv_vls_cc_1024Dv2_i(<vscale x 1 x i32> noundef %arg.coerce) [[riscv::vls_cc(1024)]] void test_vls_least_element(__attribute__((vector_size(8))) int arg) {} @@ -135,71 +135,71 @@ struct st_bf16x8x2 { typedef int __attribute__((vector_size(256))) int32x64_t; -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_too_largeDv64_i(ptr noundef align 256 dead_on_return %0) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_too_largeB16riscv_vls_cc_128Dv64_i(ptr noundef align 256 dead_on_return %0) [[riscv::vls_cc]] void test_too_large(int32x64_t arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z18test_too_large_256Dv64_i(<vscale x 16 x i32> noundef %arg.coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z18test_too_large_256B16riscv_vls_cc_256Dv64_i(<vscale x 16 x i32> noundef %arg.coerce) [[riscv::vls_cc(256)]] void test_too_large_256(int32x64_t arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z13test_st_i32x48st_i32x4(<vscale x 2 x i32> %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z13test_st_i32x4B16riscv_vls_cc_1288st_i32x4(<vscale x 2 x i32> %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4(struct st_i32x4 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z17test_st_i32x4_2568st_i32x4(<vscale x 1 x i32> %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z17test_st_i32x4_256B16riscv_vls_cc_2568st_i32x4(<vscale x 1 x i32> %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4_256(struct st_i32x4 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr113st_i32x4_arr1(<vscale x 2 x i32> %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr1B16riscv_vls_cc_12813st_i32x4_arr1(<vscale x 2 x i32> %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4_arr1(struct st_i32x4_arr1 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr1_25613st_i32x4_arr1(<vscale x 1 x i32> %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr1_256B16riscv_vls_cc_25613st_i32x4_arr1(<vscale x 1 x i32> %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4_arr1_256(struct st_i32x4_arr1 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr413st_i32x4_arr4(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr4B16riscv_vls_cc_12813st_i32x4_arr4(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4_arr4(struct st_i32x4_arr4 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr4_25613st_i32x4_arr4(target("riscv.vector.tuple", <vscale x 4 x i8>, 4) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr4_256B16riscv_vls_cc_25613st_i32x4_arr4(target("riscv.vector.tuple", <vscale x 4 x i8>, 4) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4_arr4_256(struct st_i32x4_arr4 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr813st_i32x4_arr8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z18test_st_i32x4_arr8B16riscv_vls_cc_12813st_i32x4_arr8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4_arr8(struct st_i32x4_arr8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr8_25613st_i32x4_arr8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z22test_st_i32x4_arr8_256B16riscv_vls_cc_25613st_i32x4_arr8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4_arr8_256(struct st_i32x4_arr8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x210st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x2B16riscv_vls_cc_12810st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4x2(struct st_i32x4x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x2_25610st_i32x4x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x2_256B16riscv_vls_cc_25610st_i32x4x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4x2_256(struct st_i32x4x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x8x210st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x8x2B16riscv_vls_cc_12810st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x8x2(struct st_i32x8x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x8x2_25610st_i32x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x8x2_256B16riscv_vls_cc_25610st_i32x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x8x2_256(struct st_i32x8x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_i32x64x211st_i32x64x2(ptr noundef align 256 dead_on_return %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_i32x64x2B16riscv_vls_cc_12811st_i32x64x2(ptr noundef align 256 dead_on_return %arg) [[riscv::vls_cc]] void test_st_i32x64x2(struct st_i32x64x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr noundef align 256 dead_on_return %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_i32x64x2_256B16riscv_vls_cc_25611st_i32x64x2(ptr noundef align 256 dead_on_return %arg) [[riscv::vls_cc(256)]] void test_st_i32x64x2_256(struct st_i32x64x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x310st_i32x4x3(target("riscv.vector.tuple", <vscale x 8 x i8>, 3) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x3B16riscv_vls_cc_12810st_i32x4x3(target("riscv.vector.tuple", <vscale x 8 x i8>, 3) %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4x3(struct st_i32x4x3 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x3_25610st_i32x4x3(target("riscv.vector.tuple", <vscale x 4 x i8>, 3) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x3_256B16riscv_vls_cc_25610st_i32x4x3(target("riscv.vector.tuple", <vscale x 4 x i8>, 3) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4x3_256(struct st_i32x4x3 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x810st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x8B16riscv_vls_cc_12810st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg.target_coerce) [[riscv::vls_cc]] void test_st_i32x4x8(struct st_i32x4x8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x8_25610st_i32x4x8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x8_256B16riscv_vls_cc_25610st_i32x4x8(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_i32x4x8_256(struct st_i32x4x8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x910st_i32x4x9(ptr noundef align 16 dead_on_return %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x9B16riscv_vls_cc_12810st_i32x4x9(ptr noundef align 16 dead_on_return %arg) [[riscv::vls_cc]] void test_st_i32x4x9(struct st_i32x4x9 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x9_25610st_i32x4x9(ptr noundef align 16 dead_on_return %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x9_256B16riscv_vls_cc_25610st_i32x4x9(ptr noundef align 16 dead_on_return %arg) [[riscv::vls_cc(256)]] void test_st_i32x4x9_256(struct st_i32x4x9 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_st_bf16x89st_bf16x8(<vscale x 8 x i8> %arg.target_coerce) -// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(128) void @_Z14test_st_bf16x89st_bf16x8(<vscale x 4 x bfloat> %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_st_bf16x8B16riscv_vls_cc_1289st_bf16x8(<vscale x 8 x i8> %arg.target_coerce) +// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(128) void @_Z14test_st_bf16x8B16riscv_vls_cc_1289st_bf16x8(<vscale x 4 x bfloat> %arg.target_coerce) [[riscv::vls_cc]] void test_st_bf16x8(struct st_bf16x8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z18test_st_bf16x8_2569st_bf16x8(<vscale x 4 x i8> %arg.target_coerce) -// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(256) void @_Z18test_st_bf16x8_2569st_bf16x8(<vscale x 2 x bfloat> %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z18test_st_bf16x8_256B16riscv_vls_cc_2569st_bf16x8(<vscale x 4 x i8> %arg.target_coerce) +// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(256) void @_Z18test_st_bf16x8_256B16riscv_vls_cc_2569st_bf16x8(<vscale x 2 x bfloat> %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_bf16x8_256(struct st_bf16x8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_bf16x8x211st_bf16x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) -// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(128) void @_Z16test_st_bf16x8x211st_bf16x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_bf16x8x2B16riscv_vls_cc_12811st_bf16x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(128) void @_Z16test_st_bf16x8x2B16riscv_vls_cc_12811st_bf16x8x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce) [[riscv::vls_cc]] void test_st_bf16x8x2(struct st_bf16x8x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_bf16x8x2_25611st_bf16x8x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce) -// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(256) void @_Z20test_st_bf16x8x2_25611st_bf16x8x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_bf16x8x2_256B16riscv_vls_cc_25611st_bf16x8x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce) +// CHECK-LLVM-ZVFBFA: define dso_local riscv_vls_cc(256) void @_Z20test_st_bf16x8x2_256B16riscv_vls_cc_25611st_bf16x8x2(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce) [[riscv::vls_cc(256)]] void test_st_bf16x8x2_256(struct st_bf16x8x2 arg) {} diff --git a/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp b/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp new file mode 100644 index 0000000000000..44e9a9b692deb --- /dev/null +++ b/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple riscv32-none-linux-gnu %s -emit-llvm -o - \ +// RUN: -target-feature +zve64d | FileCheck %s +// RUN: %clang_cc1 -triple riscv64-none-linux-gnu %s -emit-llvm -o - \ +// RUN: -target-feature +zve64d | FileCheck %s + +// The psABI requires a function using a standard calling convention variant to +// append an ABI tag to its mangled name. + +// CHECK-DAG: @_Z14default_vls_ccB16riscv_vls_cc_128v +__attribute__((riscv_vls_cc)) void default_vls_cc() {} + +// CHECK-DAG: @_Z7vlen_32B15riscv_vls_cc_32v +__attribute__((riscv_vls_cc(32))) void vlen_32() {} + +// CHECK-DAG: @_Z8vlen_128B16riscv_vls_cc_128v +__attribute__((riscv_vls_cc(128))) void vlen_128() {} + +// CHECK-DAG: @_Z10vlen_65536B18riscv_vls_cc_65536v +__attribute__((riscv_vls_cc(65536))) void vlen_65536() {} + +// The ABI_VLEN is part of the tag, so functions that differ only in ABI_VLEN +// get different mangled names. +// CHECK-DAG: @_ZN3v641fB15riscv_vls_cc_64Ev +namespace v64 { __attribute__((riscv_vls_cc(64))) void f() {} } +// CHECK-DAG: @_ZN4v5121fB16riscv_vls_cc_512Ev +namespace v512 { __attribute__((riscv_vls_cc(512))) void f() {} } + +// The calling convention can also come from a typedef. +typedef void vls_fn_t(void) __attribute__((riscv_vls_cc(256))); +// CHECK-DAG: @_Z12from_typedefB16riscv_vls_cc_256v +vls_fn_t from_typedef; +void from_typedef() {} + +// The tag is sorted together with an explicit abi_tag. +// CHECK-DAG: @_Z6taggedB16riscv_vls_cc_128B4userv +__attribute__((abi_tag("user"), riscv_vls_cc(128))) void tagged() {} + +namespace ns { +struct S { + // CHECK-DAG: @_ZN2ns1S6memberB16riscv_vls_cc_128Ev + __attribute__((riscv_vls_cc(128))) void member() {} +}; +void instantiate() { S().member(); } +} // namespace ns + +// CHECK-DAG: @_Z9template_B16riscv_vls_cc_128IiEvT_ +template <typename T> __attribute__((riscv_vls_cc(128))) void template_(T) {} +template void template_<int>(int); + +// The VLA vector calling convention variant has no ABI tag. +// CHECK-DAG: @_Z9vector_ccv +__attribute__((riscv_vector_cc)) void vector_cc() {} + +// CHECK-DAG: @_Z5plainv +void plain() {} >From e49422480d639760f45fbc0abc89d6568c73d774 Mon Sep 17 00:00:00 2001 From: Kito Cheng <[email protected]> Date: Thu, 20 Aug 2026 23:06:12 +0800 Subject: [PATCH 2/5] fixup! [Clang][RISCV] Mangle the ABI tag of a standard calling convention variant --- clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp b/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp index 44e9a9b692deb..a164ce0d814af 100644 --- a/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp +++ b/clang/test/CodeGenCXX/riscv-mangle-vls-cc.cpp @@ -51,5 +51,9 @@ template void template_<int>(int); // CHECK-DAG: @_Z9vector_ccv __attribute__((riscv_vector_cc)) void vector_cc() {} +// CHECK-DAG: @"_ZNK3$_0clB16riscv_vls_cc_128Ev" +auto lam = []() __attribute__((riscv_vls_cc(128))) {}; +void use_lam() { lam(); } + // CHECK-DAG: @_Z5plainv void plain() {} >From b87233c9eaeb90ee3604ad4f92c6115300caa91b Mon Sep 17 00:00:00 2001 From: Kito Cheng <[email protected]> Date: Thu, 20 Aug 2026 23:19:14 +0800 Subject: [PATCH 3/5] fixup! [Clang][RISCV] Mangle the ABI tag of a standard calling convention variant --- clang/include/clang/Sema/Sema.h | 4 ++++ clang/lib/AST/ItaniumMangle.cpp | 39 ------------------------------- clang/lib/Sema/SemaDecl.cpp | 41 +++++++++++++++++++++++++++++++++ clang/lib/Sema/SemaLambda.cpp | 3 +++ 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 778c1a2f5c427..f64d47a9aff84 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4066,6 +4066,10 @@ class Sema final : public SemaBase { MultiTemplateParamsArg TemplateParamLists, bool &AddToScope); + /// Attach the ABI tag a standard calling convention variant requires, as an + /// implicit abi_tag attribute. Call this once the function type is final. + void addImplicitCallingConvAbiTag(FunctionDecl *FD); + /// AddOverriddenMethods - See if a method overrides any in the base classes, /// and if so, check that it's a valid override and remember it. bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d20964a969f64..f8e6b898be250 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -213,40 +213,6 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { /// @} }; -/// Return the ABI tag that a function using a standard calling convention -/// variant has to append to its name, or an empty string if the function does -/// not use such a variant. -static StringRef getCallingConvAbiTag(const NamedDecl *ND) { - const auto *FD = dyn_cast<FunctionDecl>(ND); - if (!FD) - return {}; - - const auto *FT = FD->getType()->getAs<FunctionType>(); - if (!FT) - return {}; - - switch (FT->getCallConv()) { -#define CC_VLS_CASE(ABI_VLEN) \ - case CC_RISCVVLSCall_##ABI_VLEN: \ - return "riscv_vls_cc_" #ABI_VLEN; - CC_VLS_CASE(32) - CC_VLS_CASE(64) - CC_VLS_CASE(128) - CC_VLS_CASE(256) - CC_VLS_CASE(512) - CC_VLS_CASE(1024) - CC_VLS_CASE(2048) - CC_VLS_CASE(4096) - CC_VLS_CASE(8192) - CC_VLS_CASE(16384) - CC_VLS_CASE(32768) - CC_VLS_CASE(65536) -#undef CC_VLS_CASE - default: - return {}; - } -} - /// Manage the mangling of a single name. class CXXNameMangler { ItaniumMangleContextImpl &Context; @@ -350,11 +316,6 @@ class CXXNameMangler { llvm::append_range(TagList, AbiTag->tags()); } - if (StringRef CCTag = getCallingConvAbiTag(ND); !CCTag.empty()) { - UsedAbiTags.push_back(CCTag); - TagList.push_back(CCTag); - } - llvm::append_range(UsedAbiTags, AdditionalAbiTags); llvm::append_range(TagList, AdditionalAbiTags); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ae8c26808a164..37adfc3f254ff 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10111,6 +10111,46 @@ static bool isStdBuiltin(ASTContext &Ctx, FunctionDecl *FD, } } +void Sema::addImplicitCallingConvAbiTag(FunctionDecl *FD) { + const auto *FT = FD->getType()->getAs<FunctionType>(); + if (!FT) + return; + + StringRef Tag; + switch (FT->getCallConv()) { +#define CC_VLS_CASE(ABI_VLEN) \ + case CC_RISCVVLSCall_##ABI_VLEN: \ + Tag = "riscv_vls_cc_" #ABI_VLEN; \ + break; + CC_VLS_CASE(32) + CC_VLS_CASE(64) + CC_VLS_CASE(128) + CC_VLS_CASE(256) + CC_VLS_CASE(512) + CC_VLS_CASE(1024) + CC_VLS_CASE(2048) + CC_VLS_CASE(4096) + CC_VLS_CASE(8192) + CC_VLS_CASE(16384) + CC_VLS_CASE(32768) + CC_VLS_CASE(65536) +#undef CC_VLS_CASE + default: + return; + } + + SmallVector<StringRef, 4> Tags; + if (const auto *Old = FD->getAttr<AbiTagAttr>()) + llvm::append_range(Tags, Old->tags()); + if (llvm::is_contained(Tags, Tag)) + return; + Tags.push_back(Tag); + + auto *Attr = AbiTagAttr::CreateImplicit(Context, Tags.data(), Tags.size()); + FD->dropAttr<AbiTagAttr>(); + FD->addAttr(Attr); +} + NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -10742,6 +10782,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Handle attributes. ProcessDeclAttributes(S, NewFD, D); + addImplicitCallingConvAbiTag(NewFD); const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>(); if (Context.getTargetInfo().getTriple().isAArch64() && NewTVA && !NewTVA->isDefaultVersion() && diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index bbe93f6ab8a40..1588beaf30051 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1098,6 +1098,9 @@ void Sema::CompleteLambdaCallOperator( } buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType); + + // Not built by ActOnFunctionDeclarator, so tag it here. + addImplicitCallingConvAbiTag(Method); } void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, >From 4747a72ceba11048b6887bc8b78347adc781280c Mon Sep 17 00:00:00 2001 From: Kito Cheng <[email protected]> Date: Thu, 20 Aug 2026 23:29:58 +0800 Subject: [PATCH 4/5] fixup! [Clang][RISCV] Mangle the ABI tag of a standard calling convention variant --- clang/lib/Sema/SemaDecl.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 37adfc3f254ff..6bbec1f4133fa 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10139,16 +10139,22 @@ void Sema::addImplicitCallingConvAbiTag(FunctionDecl *FD) { return; } + const auto *Old = FD->getAttr<AbiTagAttr>(); SmallVector<StringRef, 4> Tags; - if (const auto *Old = FD->getAttr<AbiTagAttr>()) + if (Old) llvm::append_range(Tags, Old->tags()); if (llvm::is_contained(Tags, Tag)) return; Tags.push_back(Tag); - auto *Attr = AbiTagAttr::CreateImplicit(Context, Tags.data(), Tags.size()); + // Keep a location on the attribute, so that diagnostics about it still point + // at something: the written attribute if there is one, else the function. + AbiTagAttr *Merged = + Old ? AbiTagAttr::Create(Context, Tags.data(), Tags.size(), *Old) + : AbiTagAttr::CreateImplicit(Context, Tags.data(), Tags.size(), + FD->getLocation()); FD->dropAttr<AbiTagAttr>(); - FD->addAttr(Attr); + FD->addAttr(Merged); } NamedDecl* >From b2ca2ec21c61e148a9c0e01c98635f33d5c2e5ed Mon Sep 17 00:00:00 2001 From: Kito Cheng <[email protected]> Date: Thu, 20 Aug 2026 23:58:27 +0800 Subject: [PATCH 5/5] fixup --- clang/lib/Sema/SemaDecl.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6bbec1f4133fa..c2f57cef3dc94 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10147,8 +10147,6 @@ void Sema::addImplicitCallingConvAbiTag(FunctionDecl *FD) { return; Tags.push_back(Tag); - // Keep a location on the attribute, so that diagnostics about it still point - // at something: the written attribute if there is one, else the function. AbiTagAttr *Merged = Old ? AbiTagAttr::Create(Context, Tags.data(), Tags.size(), *Old) : AbiTagAttr::CreateImplicit(Context, Tags.data(), Tags.size(), _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
