Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5916,6 +5916,7 @@ MachineFunction &MF = DAG.getMachineFunction(); const Function &CallerF = MF.getFunction(); CallingConv::ID CallerCC = CallerF.getCallingConv(); + bool IsCalleeWin64 = Subtarget->isCallingConvWin64(CalleeCC); // Functions using the C or Fast calling convention that have an SVE signature // preserve more registers and should assume the SVE_VectorCall CC. @@ -5991,7 +5992,20 @@ SmallVector ArgLocs; CCState CCInfo(CalleeCC, isVarArg, MF, ArgLocs, C); - CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, true)); + unsigned NumArgs = Outs.size(); + for (unsigned i = 0; i != NumArgs; ++i) { + MVT ArgVT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + bool UseVarArgCC = !Outs[i].IsFixed; + // On Windows, the fixed arguments in a vararg call are passed in GPRs + // too, so use the vararg CC to force them to integer registers. + if (IsCalleeWin64) + UseVarArgCC = true; + CCAssignFn *AssignFn = CCAssignFnForCall(CalleeCC, UseVarArgCC); + bool Res = AssignFn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo); + assert(!Res && "Call operand has unhandled type"); + (void)Res; + } for (const CCValAssign &ArgLoc : ArgLocs) if (!ArgLoc.isRegLoc()) return false; @@ -6022,7 +6036,20 @@ SmallVector ArgLocs; CCState CCInfo(CalleeCC, isVarArg, MF, ArgLocs, C); - CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, isVarArg)); + unsigned NumArgs = Outs.size(); + for (unsigned i = 0; i != NumArgs; ++i) { + MVT ArgVT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + bool UseVarArgCC = isVarArg && !Outs[i].IsFixed; + // On Windows, the fixed arguments in a vararg call are passed in GPRs + // too, so use the vararg CC to force them to integer registers. + if (isVarArg && IsCalleeWin64) + UseVarArgCC = true; + CCAssignFn *AssignFn = CCAssignFnForCall(CalleeCC, UseVarArgCC); + bool Res = AssignFn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo); + assert(!Res && "Call operand has unhandled type"); + (void)Res; + } const AArch64FunctionInfo *FuncInfo = MF.getInfo(); Index: llvm/test/CodeGen/AArch64/darwinpcs-musttail.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/darwinpcs-musttail.ll @@ -0,0 +1,17 @@ +; With Darwin PCS, non-virtual thunks generated are generated with musttail +; and are expected to build +; RUN: llc -mtriple=arm64-apple-ios5.0.0 < %s | FileCheck %s + +; CHECK-LABEL: __ZThn16_N1C3addEPKcz: +; CHECK: b __ZN1C3addEPKcz + +%class.C = type { %class.A.base, [4 x i8], %class.B.base, [4 x i8] } +%class.A.base = type <{ i32 (...)**, i32 }> +%class.B.base = type <{ i32 (...)**, i32 }> + +declare void @_ZN1C3addEPKcz(%class.C*, i8*, ...) unnamed_addr #0 align 2 + +define void @_ZThn16_N1C3addEPKcz(%class.C* %0, i8* %1, ...) unnamed_addr #0 align 2 { + musttail call void (%class.C*, i8*, ...) @_ZN1C3addEPKcz(%class.C* noundef nonnull align 8 dereferenceable(28) undef, i8* noundef %1, ...) + ret void +}