[clang] [AArch64][Clang] Limit variadic onstack args to 8 bytes on Arm64EC. (PR #154578)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 20 10:25:46 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Billy Laws (bylaws)
<details>
<summary>Changes</summary>
This is part of the ABI and ensures the aarch64 variadic layout matches the x64 one.
CC: @<!-- -->cjacek @<!-- -->efriedma-quic
---
Full diff: https://github.com/llvm/llvm-project/pull/154578.diff
2 Files Affected:
- (modified) clang/lib/CodeGen/Targets/AArch64.cpp (+6-4)
- (modified) clang/test/CodeGen/AArch64/varargs-ms.c (+17-1)
``````````diff
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 289f8a9dcf211..1e00bd76f1a79 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -474,8 +474,9 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
}
- // Aggregates <= 16 bytes are passed directly in registers or on the stack.
- if (Size <= 128) {
+ // Aggregates <= 16 bytes (8 bytes for variadic Arm64EC) are passed directly in registers or on the stack.
+ uint64_t MaxDirectSize = (IsVariadicFn && getTarget().getTriple().isWindowsArm64EC()) ? 64 : 128;
+ if (Size <= MaxDirectSize) {
unsigned Alignment;
if (Kind == AArch64ABIKind::AAPCS) {
Alignment = getContext().getTypeUnadjustedAlign(Ty);
@@ -1152,8 +1153,9 @@ RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty, AggValueSlot Slot) const {
bool IsIndirect = false;
- // Composites larger than 16 bytes are passed by reference.
- if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
+ // Composites larger than 16 bytes (8 bytes on Arm64EC) are passed by reference.
+ uint64_t MaxDirectSize = getTarget().getTriple().isWindowsArm64EC() ? 64 : 128;
+ if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > MaxDirectSize)
IsIndirect = true;
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
diff --git a/clang/test/CodeGen/AArch64/varargs-ms.c b/clang/test/CodeGen/AArch64/varargs-ms.c
index a9393d4c5ab6a..d311a4b8c952c 100644
--- a/clang/test/CodeGen/AArch64/varargs-ms.c
+++ b/clang/test/CodeGen/AArch64/varargs-ms.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple arm64-windows-msvc -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-windows-msvc -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-A64
+// RUN: %clang_cc1 -triple arm64ec-windows-msvc -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EC
#include <stdarg.h>
@@ -8,3 +9,18 @@ int simple_int(va_list ap) {
// CHECK: [[RESULT:%[a-z_0-9]+]] = load i32, ptr %argp.cur
// CHECK: ret i32 [[RESULT]]
}
+
+struct bigstruct {
+ int item[4];
+};
+struct bigstruct big_struct(va_list ap) {
+// CHECK-LABEL: define dso_local [2 x i64] @big_struct
+ return va_arg(ap, struct bigstruct);
+// CHECK-EC: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 8
+// CHECK-EC: [[PTR:%[0-9]+]] = load ptr, ptr %argp.cur, align 8
+// CHECK-EC: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 [[PTR]], i64 16, i1 false)
+// CHECK-A64: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 16
+// CHECK-A64: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 8 %argp.cur, i64 16, i1 false)
+// CHECK: [[RESULT:%[0-9]+]] = load [2 x i64], ptr %coerce.dive
+// CHECK: ret [2 x i64] [[RESULT]]
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/154578
More information about the cfe-commits
mailing list