https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/216849

This adds LLVM ABI library support for AArch64 argument type classification for 
scalar and matrix types that are classified as Direct. Other types are reported 
as not yet implemented.

This also adds a Clang test for the ABI handling of types which are handled by 
the library.

Assisted-by: Cursor / Grok 4.5 (test generation)

>From 607e5d87143ef3829d0e2d3654ff0036f4e4b5b1 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Mon, 17 Aug 2026 14:35:10 -0700
Subject: [PATCH] [LLVMABI][AARCH64] Add support for simple direct argument
 cases

This adds LLVM ABI library support for AArch64 argument type classification
for scalar and matrix types that are classified as Direct. Other types are
reported as not yet implemented.

This also adds a Clang test for the ABI handling of types which are handled
by the library.

Assisted-by: Cursor / Grok 4.5 (test generation)
---
 .../CodeGen/AArch64/abi-classify-arg-types.c  | 63 +++++++++++++++++++
 llvm/lib/ABI/Targets/AArch64.cpp              | 29 ++++++++-
 llvm/unittests/ABI/AArch64TargetInfoTest.cpp  | 57 ++++++++++++++++-
 3 files changed, 146 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CodeGen/AArch64/abi-classify-arg-types.c

diff --git a/clang/test/CodeGen/AArch64/abi-classify-arg-types.c 
b/clang/test/CodeGen/AArch64/abi-classify-arg-types.c
new file mode 100644
index 0000000000000..4f0933b436b4e
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/abi-classify-arg-types.c
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs 
-fenable-matrix -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,DARWIN
+// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs 
-fenable-matrix -fexperimental-abi-lowering -emit-llvm -o - %s 2>&1 | FileCheck 
%s --check-prefixes=CHECK,DARWIN --implicit-check-not="not yet implemented"
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fenable-matrix -emit-llvm -o - 
%s | FileCheck %s --check-prefixes=CHECK,AAPCS
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fenable-matrix 
-fexperimental-abi-lowering -emit-llvm -o - %s 2>&1 | FileCheck %s 
--check-prefixes=CHECK,AAPCS --implicit-check-not="not yet implemented"
+
+// This test is verifying that the LLVM ABI library classifies argument types 
in
+// the same way that Clang does without the library.
+
+// The AArch64 support in the ABI library is a work in progress. New test cases
+// will be added here as the types are implemented. Unimplemented cases will
+// report a warning if the ABI library is used.
+
+void arg_void(void) {
+}
+// CHECK: define{{.*}} void @arg_void()
+
+void arg_bool(_Bool b) {}
+// AAPCS: define{{.*}} void @arg_bool(i1 noundef %{{.*}})
+// DARWIN: define{{.*}} void @arg_bool(i1 noundef zeroext %{{.*}})
+
+void arg_char(char c) {}
+// AAPCS: define{{.*}} void @arg_char(i8 noundef %{{.*}})
+// DARWIN: define{{.*}} void @arg_char(i8 noundef signext %{{.*}})
+
+void arg_short(short s) {}
+// AAPCS: define{{.*}} void @arg_short(i16 noundef %{{.*}})
+// DARWIN: define{{.*}} void @arg_short(i16 noundef signext %{{.*}})
+
+void arg_ushort(unsigned short us) {}
+// AAPCS: define{{.*}} void @arg_ushort(i16 noundef %{{.*}})
+// DARWIN: define{{.*}} void @arg_ushort(i16 noundef zeroext %{{.*}})
+
+void arg_int(int i) {}
+// CHECK: define{{.*}} void @arg_int(i32 noundef %{{.*}})
+
+void arg_uint(unsigned int ui) {}
+// CHECK: define{{.*}} void @arg_uint(i32 noundef %{{.*}})
+
+void arg_long(long int li) {}
+// CHECK: define{{.*}} void @arg_long(i64 noundef %{{.*}})
+
+void arg_float16(_Float16 f16) {}
+// CHECK: define{{.*}} void @arg_float16(half noundef %{{.*}})
+
+void arg_fp16(__fp16 f16) {}
+// CHECK: define{{.*}} void @arg_fp16(half noundef %{{.*}})
+
+void arg_float(float f) {}
+// CHECK: define{{.*}} void @arg_float(float noundef %{{.*}})
+
+void arg_double(double d) {}
+// CHECK: define{{.*}} void @arg_double(double noundef %{{.*}})
+
+int gi;
+void arg_int_ptr(int* pi) {}
+// CHECK: define{{.*}} void @arg_int_ptr(ptr noundef %{{.*}})
+
+void arg_void_ptr(void* pv) {}
+// CHECK: define{{.*}} void @arg_void_ptr(ptr noundef %{{.*}})
+
+typedef float fx2x2_t __attribute__((matrix_type(2, 2)));
+void arg_matrix(fx2x2_t m) {}
+// CHECK: define{{.*}} void @arg_matrix(<4 x float> noundef %{{.*}})
diff --git a/llvm/lib/ABI/Targets/AArch64.cpp b/llvm/lib/ABI/Targets/AArch64.cpp
index 7aa5a893d3b13..36f4ddb95ce81 100644
--- a/llvm/lib/ABI/Targets/AArch64.cpp
+++ b/llvm/lib/ABI/Targets/AArch64.cpp
@@ -92,7 +92,34 @@ ArgInfo AArch64TargetInfo::classifyReturnType(const Type 
*RetTy,
 ArgInfo AArch64TargetInfo::classifyArgumentType(
     const Type *Ty, bool IsVariadicFn, bool IsNamedArg,
     unsigned CallingConvention, unsigned &NSRN, unsigned &NPRN) const {
-  reportNYI("Classify argument type");
+  // TODO: Handled variadic functins here when Windows Arm64 EC is supported.
+
+  if (Ty->isVector()) {
+    reportNYI("Vector argument type");
+    return ArgInfo::getDirect();
+  }
+
+  if (!passAsAggregateType(Ty)) {
+    if (const auto *IntTy = dyn_cast<IntegerType>(Ty)) {
+      if (IntTy->isBitInt()) {
+        reportNYI("BitInt argument type");
+        return ArgInfo::getDirect();
+      }
+      if (isPromotableInteger(IntTy) && isDarwinPCS()) {
+        return ArgInfo::getExtend(IntTy);
+      }
+    }
+
+    // TODO: Legal vector types will update NSRN or NPRN.
+
+    if (Ty->isFloat())
+      NSRN = std::min(NSRN + 1, 8u);
+
+    // Everything not handled above is returned directly.
+    return ArgInfo::getDirect();
+  }
+
+  reportNYI("Aggregate argument type");
   return ArgInfo::getDirect();
 }
 
diff --git a/llvm/unittests/ABI/AArch64TargetInfoTest.cpp 
b/llvm/unittests/ABI/AArch64TargetInfoTest.cpp
index 55bf7b4f6a303..df0a9bdc0de7d 100644
--- a/llvm/unittests/ABI/AArch64TargetInfoTest.cpp
+++ b/llvm/unittests/ABI/AArch64TargetInfoTest.cpp
@@ -45,7 +45,7 @@ class AArch64TargetInfoTest : public ::testing::Test {
   const ABIType *Matrix;
 
   AArch64TargetInfoTest()
-      : TB(Alloc), Bool(TB.getIntegerType(1, llvm::Align(1), /*Signed=*/true)),
+      : TB(Alloc), Bool(TB.getIntegerType(1, llvm::Align(1), 
/*Signed=*/false)),
         I8(TB.getIntegerType(8, llvm::Align(1), /*Signed=*/true)),
         U8(TB.getIntegerType(8, llvm::Align(1), /*Signed=*/false)),
         I16(TB.getIntegerType(16, llvm::Align(2), /*Signed=*/true)),
@@ -104,7 +104,7 @@ TEST_F(AArch64TargetInfoTest, 
ClassifyReturnScalarsDirectAAPCS) {
 
 // DarwinPCS returns non-promotable scalars directly. Promotable integer
 // returns are extended.
-TEST_F(AArch64TargetInfoTest, ClassifyReturnNonPromotableScalarsDirectDarwin) {
+TEST_F(AArch64TargetInfoTest, ClassifyReturnScalarsDirectOrPromotableDarwin) {
   std::unique_ptr<TargetInfo> TI =
       createAArch64TargetInfo(TB, AArch64ABIKind::DarwinPCS);
 
@@ -143,4 +143,57 @@ TEST_F(AArch64TargetInfoTest, 
ClassifyReturnScalarsDirectAAPCSSoft) {
   }
 }
 
+// Non-aggregate scalars, matrix types, and promotable integers take the Direct
+// argument path under AAPCS.
+TEST_F(AArch64TargetInfoTest, ClassifyArgumentScalarsDirectAAPCS) {
+  std::unique_ptr<TargetInfo> TI =
+      createAArch64TargetInfo(TB, AArch64ABIKind::AAPCS);
+
+  for (const ABIType *ArgTy :
+       {Bool, I8, U8, I16, U16, I32, U32, I64, U64, F32, F64, Ptr, Matrix}) {
+    std::unique_ptr<FunctionInfo> FI =
+        FunctionInfo::create(llvm::CallingConv::C, Void, {ArgTy});
+    TI->computeInfo(*FI);
+    expectUncoercedDirect(FI->getArgInfo(0).Info);
+  }
+}
+
+// DarwinPCS passes non-promotable scalars directly. Promotable integer
+// arguments are extended.
+TEST_F(AArch64TargetInfoTest, ClassifyArgumentScalarsDirectOrPromotableDarwin) 
{
+  std::unique_ptr<TargetInfo> TI =
+      createAArch64TargetInfo(TB, AArch64ABIKind::DarwinPCS);
+
+  for (const ABIType *ArgTy : {I32, U32, I64, U64, F32, F64, Ptr, Matrix}) {
+    std::unique_ptr<FunctionInfo> FI =
+        FunctionInfo::create(llvm::CallingConv::C, Void, {ArgTy});
+    TI->computeInfo(*FI);
+    expectUncoercedDirect(FI->getArgInfo(0).Info);
+  }
+
+  for (const ABIType *ArgTy : {Bool, I8, U8, I16, U16}) {
+    std::unique_ptr<FunctionInfo> FI =
+        FunctionInfo::create(llvm::CallingConv::C, Void, {ArgTy});
+    TI->computeInfo(*FI);
+
+    bool IsSigned = llvm::cast<llvm::abi::IntegerType>(ArgTy)->isSigned();
+    expectExtendInteger(FI->getArgInfo(0).Info, ArgTy, IsSigned);
+  }
+}
+
+// Non-aggregate scalars, matrix types, and promotable integers take the Direct
+// argument path under AAPCSSoft.
+TEST_F(AArch64TargetInfoTest, ClassifyArgumentScalarsDirectAAPCSSoft) {
+  std::unique_ptr<TargetInfo> TI =
+      createAArch64TargetInfo(TB, AArch64ABIKind::AAPCSSoft);
+
+  for (const ABIType *ArgTy :
+       {Bool, I8, U8, I16, U16, I32, U32, I64, U64, F32, F64, Ptr, Matrix}) {
+    std::unique_ptr<FunctionInfo> FI =
+        FunctionInfo::create(llvm::CallingConv::C, Void, {ArgTy});
+    TI->computeInfo(*FI);
+    expectUncoercedDirect(FI->getArgInfo(0).Info);
+  }
+}
+
 } // namespace

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to