[clang] [Clang][AArch64] Include SME attributes in the name mangling of function types (PR #114209)

Kerry McLaughlin via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 30 04:30:57 PDT 2024


https://github.com/kmclaughlin-arm created https://github.com/llvm/llvm-project/pull/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, streaming_mode, za_state, zt0_state>`

For example, the following function:

  `void f(svint8_t (*fn)() __arm_streaming) { fn(); }`

would be mangled as:

  `fP9__SME_ATTRSIFu10__SVInt8_tELj1ELj0ELj0EE`

See https://github.com/ARM-software/abi-aa/pull/290

>From ff5b6defc0df704f63fffabc731bcd38a1e24d3b Mon Sep 17 00:00:00 2001
From: Kerry McLaughlin <kerry.mclaughlin at arm.com>
Date: Tue, 15 Oct 2024 15:22:56 +0000
Subject: [PATCH] [Clang][AArch64] Include SME attributes in the name mangling
 of function types.

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, streaming_mode, za_state, zt0_state>

For example, the following function:

  void f(svint8_t (*fn)() __arm_streaming) { fn(); }

is mangled as:

  fP9__SME_ATTRSIFu10__SVInt8_tELj1ELj0ELj0EE

See https://github.com/ARM-software/abi-aa/pull/290
---
 clang/lib/AST/ItaniumMangle.cpp               | 41 ++++++++++++
 .../CodeGenCXX/aarch64-mangle-sme-atts.cpp    | 65 +++++++++++++++++++
 2 files changed, 106 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/aarch64-mangle-sme-atts.cpp

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b3e46508cf596d..2a015b4c45297e 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -575,6 +575,7 @@ class CXXNameMangler {
   static StringRef getCallingConvQualifierName(CallingConv CC);
   void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info);
   void mangleExtFunctionInfo(const FunctionType *T);
+  void mangleSMEAttrs(unsigned SMEAttrs);
   void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
                               const FunctionDecl *FD = nullptr);
   void mangleNeonVectorType(const VectorType *T);
@@ -3535,6 +3536,39 @@ void CXXNameMangler::mangleExtFunctionInfo(const FunctionType *T) {
   // FIXME: noreturn
 }
 
+bool hasSharedState(unsigned SMEAttrs) {
+  switch (SMEAttrs) {
+  case FunctionType::ARM_In:
+  case FunctionType::ARM_Out:
+  case FunctionType::ARM_InOut:
+  case FunctionType::ARM_Preserves:
+    return true;
+  default:
+    return false;
+  }
+}
+
+void CXXNameMangler::mangleSMEAttrs(unsigned SMEAttrs) {
+  if (!SMEAttrs)
+    return;
+
+  // Streaming Mode
+  if (SMEAttrs & FunctionType::SME_PStateSMEnabledMask)
+    Out << "Lj1E";
+  else if (SMEAttrs & FunctionType::SME_PStateSMCompatibleMask)
+    Out << "Lj2E";
+  else
+    Out << "Lj0E";
+
+  // ZA & ZT0 State
+  Out << (hasSharedState(FunctionType::getArmZAState(SMEAttrs)) ? "Lj1E"
+                                                                : "Lj0E");
+  Out << (hasSharedState(FunctionType::getArmZT0State(SMEAttrs)) ? "Lj1E"
+                                                                 : "Lj0E");
+
+  return;
+}
+
 void
 CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
   // Vendor-specific qualifiers are emitted in reverse alphabetical order.
@@ -3572,6 +3606,11 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
 // <function-type> ::= [<CV-qualifiers>] F [Y]
 //                      <bare-function-type> [<ref-qualifier>] E
 void CXXNameMangler::mangleType(const FunctionProtoType *T) {
+  unsigned SMEAttrs = T->getAArch64SMEAttributes();
+
+  if (SMEAttrs)
+    Out << "11__SME_ATTRSI";
+
   mangleExtFunctionInfo(T);
 
   // Mangle CV-qualifiers, if present.  These are 'this' qualifiers,
@@ -3605,6 +3644,8 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
   // Mangle the ref-qualifier, if present.
   mangleRefQualifier(T->getRefQualifier());
 
+  mangleSMEAttrs(SMEAttrs);
+
   Out << 'E';
 }
 
diff --git a/clang/test/CodeGenCXX/aarch64-mangle-sme-atts.cpp b/clang/test/CodeGenCXX/aarch64-mangle-sme-atts.cpp
new file mode 100644
index 00000000000000..16d4111cdfaaa1
--- /dev/null
+++ b/clang/test/CodeGenCXX/aarch64-mangle-sme-atts.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme -target-feature +sme2 %s -emit-llvm -o - | FileCheck %s
+
+typedef __attribute__((neon_vector_type(2))) int int32x2_t;
+
+//
+// Streaming-Mode Attributes
+//
+
+// CHECK: define dso_local void @_Z12fn_streamingP11__SME_ATTRSIFvvLj1ELj0ELj0EE( 
+void fn_streaming(void (*foo)() __arm_streaming) { foo(); }
+
+// CHECK: define dso_local void @_Z12fn_streamingP11__SME_ATTRSIFivLj2ELj0ELj0EE(
+void fn_streaming(int (*foo)() __arm_streaming_compatible) { foo(); }
+
+//
+// ZA Attributes
+//
+
+// CHECK: define dso_local void @_Z15fn_za_preservedP11__SME_ATTRSIF11__Int32x2_tvLj0ELj1ELj0EE(
+__arm_new("za") void fn_za_preserved(int32x2_t (*foo)() __arm_preserves("za")) { foo(); }
+
+// CHECK: define dso_local void @_Z8fn_za_inP11__SME_ATTRSIFvu13__SVFloat64_tLj0ELj1ELj0EES_(
+__arm_new("za") void fn_za_in(void (*foo)(__SVFloat64_t) __arm_in("za"), __SVFloat64_t x) { foo(x); }
+
+// CHECK: define dso_local noundef i32 @_Z9fn_za_outP11__SME_ATTRSIFivLj0ELj1ELj0EE(
+__arm_new("za") int fn_za_out(int (*foo)() __arm_out("za")) { return foo(); }
+
+// CHECK: define dso_local void @_Z11fn_za_inoutP11__SME_ATTRSIFvvLj0ELj1ELj0EE(
+__arm_new("za") void fn_za_inout(void (*foo)() __arm_inout("za")) { foo(); }
+
+
+//
+// ZT0 Attributes
+//
+
+// CHECK: define dso_local void @_Z16fn_zt0_preservedP11__SME_ATTRSIFivLj0ELj0ELj1EE(
+__arm_new("zt0") void fn_zt0_preserved(int (*foo)() __arm_preserves("zt0")) { foo(); }
+
+// CHECK: define dso_local void @_Z9fn_zt0_inP11__SME_ATTRSIFivLj0ELj0ELj1EE(
+__arm_new("zt0") void fn_zt0_in(int (*foo)() __arm_in("zt0")) { foo(); }
+
+// CHECK: define dso_local void @_Z10fn_zt0_outP11__SME_ATTRSIFivLj0ELj0ELj1EE(
+__arm_new("zt0") void fn_zt0_out(int (*foo)() __arm_out("zt0")) { foo(); }
+
+// CHECK: define dso_local void @_Z12fn_zt0_inoutP11__SME_ATTRSIFivLj0ELj0ELj1EE(
+__arm_new("zt0") void fn_zt0_inout(int (*foo)() __arm_inout("zt0")) { foo(); }
+
+//
+// No SME Attributes
+//
+
+// CHECK: define dso_local void @_Z12no_sme_attrsPFvvE(
+void no_sme_attrs(void (*foo)()) { foo(); }
+
+// CHECK: define dso_local void @_Z24locally_streaming_callerPFvvE(
+__arm_locally_streaming void locally_streaming_caller(void (*foo)()) { foo(); }
+
+// CHECK: define dso_local void @_Z16streaming_callerv(
+void streaming_caller() __arm_streaming {}
+
+// CHECK: define dso_local void @_Z16za_shared_callerv(
+void za_shared_caller() __arm_in("za") {}
+
+// CHECK: define dso_local void @_Z17zt0_shared_callerv(
+void zt0_shared_caller() __arm_out("zt0") {}



More information about the cfe-commits mailing list