[clang] [AArch64][Clang] Limit variadic onstack args to 8 bytes on Arm64EC. (PR #154578)
Billy Laws via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 20 10:25:02 PDT 2025
https://github.com/bylaws created https://github.com/llvm/llvm-project/pull/154578
This is part of the ABI and ensures the aarch64 variadic layout matches the x64 one.
CC: @cjacek @efriedma-quic
>From 3aecb6eeeeda0b78a8ee6dc1aa19d4331f16ab8f Mon Sep 17 00:00:00 2001
From: Billy Laws <blaws05 at gmail.com>
Date: Thu, 24 Jul 2025 16:04:25 +0100
Subject: [PATCH] [AArch64][Clang] Limit variadic onstack args to 8 bytes on
Arm64EC.
---
clang/lib/CodeGen/Targets/AArch64.cpp | 10 ++++++----
clang/test/CodeGen/AArch64/varargs-ms.c | 18 +++++++++++++++++-
2 files changed, 23 insertions(+), 5 deletions(-)
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]]
+}
More information about the cfe-commits
mailing list