diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2450,6 +2450,12 @@ return isX86VectorCallAggregateSmallEnough(NumMembers); } + ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty) { + unsigned FreeSSERegs = 0; + return classify(Ty, FreeSSERegs, /*IsReturnType=*/false, + /*IsVectorCall=*/false, /*IsRegCall=*/false); + } + private: ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs, bool IsReturnType, bool IsVectorCall, bool IsRegCall) const; @@ -5735,6 +5741,13 @@ unsigned CallingConvention) const { Ty = useFirstFieldIfTransparentUnion(Ty); + if (IsVariadic && getTarget().getTriple().isWindowsArm64EC()) { + // Arm64EC varargs functions use the x86_64 classification rules, + // not the AArch64 ABI rules. + WinX86_64ABIInfo Win64ABIInfo(CGT, X86AVXABILevel::None); + return Win64ABIInfo.classifyArgForArm64ECVarArg(Ty); + } + // Handle illegal vector types here. if (isIllegalVectorType(Ty)) return coerceIllegalVector(Ty); diff --git a/clang/test/CodeGen/arm64ec.c b/clang/test/CodeGen/arm64ec.c --- a/clang/test/CodeGen/arm64ec.c +++ b/clang/test/CodeGen/arm64ec.c @@ -2,6 +2,8 @@ // CHECK: @g = alias void ([2 x float], [4 x float]), void ([2 x float], [4 x float])* @"#g" // CHECK: define dso_local void @"#g" +// CHECK: call void (i64, ...) @f(i64 %{{.*}}, %struct.B* noundef %{{.*}}) typedef struct { float x[2]; } A; typedef struct { float x[4]; } B; -void g(A a, B b) { } +void f(A a, ...); +void g(A a, B b) { f(a, b); } diff --git a/clang/test/CodeGenCXX/arm64ec.cpp b/clang/test/CodeGenCXX/arm64ec.cpp --- a/clang/test/CodeGenCXX/arm64ec.cpp +++ b/clang/test/CodeGenCXX/arm64ec.cpp @@ -2,6 +2,8 @@ // CHECK: @"?g@@YAXUA@@UB@@@Z" = alias void ([2 x float], [4 x float]), void ([2 x float], [4 x float])* @"?g@@$$hYAXUA@@UB@@@Z" // CHECK: define dso_local void @"?g@@$$hYAXUA@@UB@@@Z" +// CHECK: call void (i64, ...) @"?f@@YAXUA@@ZZ"(i64 %{{.*}}, %struct.B* noundef %{{.*}}) typedef struct { float x[2]; } A; typedef struct { float x[4]; } B; -void g(A a, B b) { } +void f(A a, ...); +void g(A a, B b) { f(a, b); }