Skip to content

Commit 34d4cd8

Browse files
[Clang][AArch64] Include SME attributes in the name mangling of function types (#114209)
Similar to arm_sve_vector_bits, the mangling of function types is implemented as a pseudo template if there are any SME attributes present, i.e. `__SME_ATTRS<normal_function_type, sme_state>` For example, the following function: `void f(svint8_t (*fn)() __arm_streaming) { fn(); }` would be mangled as: `_Z1fP11__SME_ATTRSIFu10__SVInt8_tELj1EE` See ARM-software/acle#358
1 parent fe1c4f0 commit 34d4cd8

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ class CXXNameMangler {
574574
static StringRef getCallingConvQualifierName(CallingConv CC);
575575
void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info);
576576
void mangleExtFunctionInfo(const FunctionType *T);
577+
void mangleSMEAttrs(unsigned SMEAttrs);
577578
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
578579
const FunctionDecl *FD = nullptr);
579580
void mangleNeonVectorType(const VectorType *T);
@@ -3532,6 +3533,69 @@ void CXXNameMangler::mangleExtFunctionInfo(const FunctionType *T) {
35323533
// FIXME: noreturn
35333534
}
35343535

3536+
enum class AAPCSBitmaskSME : unsigned {
3537+
ArmStreamingBit = 1 << 0,
3538+
ArmStreamingCompatibleBit = 1 << 1,
3539+
ArmAgnosticSMEZAStateBit = 1 << 2,
3540+
ZA_Shift = 3,
3541+
ZT0_Shift = 6,
3542+
NoState = 0b000,
3543+
ArmIn = 0b001,
3544+
ArmOut = 0b010,
3545+
ArmInOut = 0b011,
3546+
ArmPreserves = 0b100,
3547+
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ArmPreserves << ZT0_Shift)
3548+
};
3549+
3550+
static AAPCSBitmaskSME encodeAAPCSZAState(unsigned SMEAttrs) {
3551+
switch (SMEAttrs) {
3552+
case FunctionType::ARM_None:
3553+
return AAPCSBitmaskSME::NoState;
3554+
case FunctionType::ARM_In:
3555+
return AAPCSBitmaskSME::ArmIn;
3556+
case FunctionType::ARM_Out:
3557+
return AAPCSBitmaskSME::ArmOut;
3558+
case FunctionType::ARM_InOut:
3559+
return AAPCSBitmaskSME::ArmInOut;
3560+
case FunctionType::ARM_Preserves:
3561+
return AAPCSBitmaskSME::ArmPreserves;
3562+
default:
3563+
llvm_unreachable("Unrecognised SME attribute");
3564+
}
3565+
}
3566+
3567+
// The mangling scheme for function types which have SME attributes is
3568+
// implemented as a "pseudo" template:
3569+
//
3570+
// '__SME_ATTRS<<normal_function_type>, <sme_state>>'
3571+
//
3572+
// Combining the function type with a bitmask representing the streaming and ZA
3573+
// properties of the function's interface.
3574+
//
3575+
// Mangling of SME keywords is described in more detail in the AArch64 ACLE:
3576+
// https://github.com/ARM-software/acle/blob/main/main/acle.md#c-mangling-of-sme-keywords
3577+
//
3578+
void CXXNameMangler::mangleSMEAttrs(unsigned SMEAttrs) {
3579+
if (!SMEAttrs)
3580+
return;
3581+
3582+
AAPCSBitmaskSME Bitmask = AAPCSBitmaskSME(0);
3583+
if (SMEAttrs & FunctionType::SME_PStateSMEnabledMask)
3584+
Bitmask |= AAPCSBitmaskSME::ArmStreamingBit;
3585+
else if (SMEAttrs & FunctionType::SME_PStateSMCompatibleMask)
3586+
Bitmask |= AAPCSBitmaskSME::ArmStreamingCompatibleBit;
3587+
3588+
// TODO: Must represent __arm_agnostic("sme_za_state")
3589+
3590+
Bitmask |= encodeAAPCSZAState(FunctionType::getArmZAState(SMEAttrs))
3591+
<< AAPCSBitmaskSME::ZA_Shift;
3592+
3593+
Bitmask |= encodeAAPCSZAState(FunctionType::getArmZT0State(SMEAttrs))
3594+
<< AAPCSBitmaskSME::ZT0_Shift;
3595+
3596+
Out << "Lj" << static_cast<unsigned>(Bitmask) << "EE";
3597+
}
3598+
35353599
void
35363600
CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
35373601
// Vendor-specific qualifiers are emitted in reverse alphabetical order.
@@ -3569,6 +3633,11 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
35693633
// <function-type> ::= [<CV-qualifiers>] F [Y]
35703634
// <bare-function-type> [<ref-qualifier>] E
35713635
void CXXNameMangler::mangleType(const FunctionProtoType *T) {
3636+
unsigned SMEAttrs = T->getAArch64SMEAttributes();
3637+
3638+
if (SMEAttrs)
3639+
Out << "11__SME_ATTRSI";
3640+
35723641
mangleExtFunctionInfo(T);
35733642

35743643
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
@@ -3603,6 +3672,8 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
36033672
mangleRefQualifier(T->getRefQualifier());
36043673

36053674
Out << 'E';
3675+
3676+
mangleSMEAttrs(SMEAttrs);
36063677
}
36073678

36083679
void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme -target-feature +sme2 %s -emit-llvm -o - | FileCheck %s
2+
3+
typedef __attribute__((neon_vector_type(2))) int int32x2_t;
4+
5+
//
6+
// Streaming-Mode Attributes
7+
//
8+
9+
// CHECK: define dso_local void @_Z12fn_streamingP11__SME_ATTRSIFvvELj1EE
10+
void fn_streaming(void (*foo)() __arm_streaming) { foo(); }
11+
12+
// CHECK: define dso_local void @_Z23fn_streaming_compatibleP11__SME_ATTRSIFivELj2EE(
13+
void fn_streaming_compatible(int (*foo)() __arm_streaming_compatible) { foo(); }
14+
15+
//
16+
// ZA Attributes
17+
//
18+
19+
// CHECK: define dso_local void @_Z15fn_za_preservedP11__SME_ATTRSIF11__Int32x2_tvELj32EE(
20+
__arm_new("za") void fn_za_preserved(int32x2_t (*foo)() __arm_preserves("za")) { foo(); }
21+
22+
// CHECK: define dso_local void @_Z8fn_za_inP11__SME_ATTRSIFvu13__SVFloat64_tELj8EES_(
23+
__arm_new("za") void fn_za_in(void (*foo)(__SVFloat64_t) __arm_in("za"), __SVFloat64_t x) { foo(x); }
24+
25+
// CHECK: define dso_local noundef i32 @_Z9fn_za_outP11__SME_ATTRSIFivELj16EE(
26+
__arm_new("za") int fn_za_out(int (*foo)() __arm_out("za")) { return foo(); }
27+
28+
// CHECK: define dso_local void @_Z11fn_za_inoutP11__SME_ATTRSIFvvELj24EE(
29+
__arm_new("za") void fn_za_inout(void (*foo)() __arm_inout("za")) { foo(); }
30+
31+
32+
//
33+
// ZT0 Attributes
34+
//
35+
36+
// CHECK: define dso_local void @_Z16fn_zt0_preservedP11__SME_ATTRSIFivELj256EE(
37+
__arm_new("zt0") void fn_zt0_preserved(int (*foo)() __arm_preserves("zt0")) { foo(); }
38+
39+
// CHECK: define dso_local void @_Z9fn_zt0_inP11__SME_ATTRSIFivELj64EE(
40+
__arm_new("zt0") void fn_zt0_in(int (*foo)() __arm_in("zt0")) { foo(); }
41+
42+
// CHECK: define dso_local void @_Z10fn_zt0_outP11__SME_ATTRSIFivELj128EE(
43+
__arm_new("zt0") void fn_zt0_out(int (*foo)() __arm_out("zt0")) { foo(); }
44+
45+
// CHECK: define dso_local void @_Z12fn_zt0_inoutP11__SME_ATTRSIFivELj192EE(
46+
__arm_new("zt0") void fn_zt0_inout(int (*foo)() __arm_inout("zt0")) { foo(); }
47+
48+
//
49+
// Streaming-mode, ZA & ZT0 Attributes
50+
//
51+
52+
// CHECK: define dso_local void @_Z17fn_all_attr_typesP11__SME_ATTRSIFivELj282EE(
53+
__arm_new("za") __arm_new("zt0")
54+
void fn_all_attr_types(int (*foo)() __arm_streaming_compatible __arm_inout("za") __arm_preserves("zt0"))
55+
{ foo(); }
56+
57+
//
58+
// No SME Attributes
59+
//
60+
61+
// CHECK: define dso_local void @_Z12no_sme_attrsPFvvE(
62+
void no_sme_attrs(void (*foo)()) { foo(); }
63+
64+
// CHECK: define dso_local void @_Z24locally_streaming_callerPFvvE(
65+
__arm_locally_streaming void locally_streaming_caller(void (*foo)()) { foo(); }
66+
67+
// CHECK: define dso_local void @_Z16streaming_callerv(
68+
void streaming_caller() __arm_streaming {}
69+
70+
// CHECK: define dso_local void @_Z16za_shared_callerv(
71+
void za_shared_caller() __arm_in("za") {}
72+
73+
// CHECK: define dso_local void @_Z17zt0_shared_callerv(
74+
void zt0_shared_caller() __arm_out("zt0") {}

0 commit comments

Comments
 (0)