Index: llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp @@ -514,8 +514,20 @@ for (unsigned i = 0; i < OutLocs.size(); ++i) { auto &ArgLoc = OutLocs[i]; // If it's not a register, it's fine. - if (!ArgLoc.isRegLoc()) + if (!ArgLoc.isRegLoc()) { + if (Info.IsVarArg) { + // Be conservative and disallow variadic memory operands to match SDAG's + // behaviour. + // FIXME: If the caller's calling convention is C, then we can + // potentially use its argument area. However, for cases like fastcc, + // we can't do anything. + LLVM_DEBUG( + dbgs() + << "... Cannot tail call vararg function with stack arguments\n"); + return false; + } continue; + } Register Reg = ArgLoc.getLocReg(); @@ -583,11 +595,6 @@ return false; } - if (Info.IsVarArg) { - LLVM_DEBUG(dbgs() << "... Tail calling varargs not supported yet.\n"); - return false; - } - // Byval parameters hand the function a pointer directly into the stack area // we want to reuse during a tail call. Working around this *is* possible (see // X86). @@ -641,6 +648,12 @@ assert((!Info.IsVarArg || CalleeCC == CallingConv::C) && "Unexpected variadic calling convention"); + // Before we can musttail varargs, we need to forward parameters like in + // r345641. Make sure that we don't enable musttail with varargs without + // addressing that! + assert(!(Info.IsVarArg && Info.IsMustTailCall) && + "musttail support for varargs not implemented yet!"); + // Verify that the incoming and outgoing arguments from the callee are // safe to tail call. if (!doCallerAndCalleePassArgsTheSameWay(Info, MF, InArgs)) { Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll @@ -75,22 +75,33 @@ ret i32 %call } -; Right now, this should not be tail called. -; TODO: Support this. declare void @varargs(i32, double, i64, ...) define void @test_varargs() { - ; COMMON-LABEL: name: test_varargs - ; COMMON: bb.1 (%ir-block.0): - ; COMMON: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 - ; COMMON: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00 - ; COMMON: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12 - ; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp - ; COMMON: $w0 = COPY [[C]](s32) - ; COMMON: $d0 = COPY [[C1]](s64) - ; COMMON: $x1 = COPY [[C2]](s64) - ; COMMON: BL @varargs, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $d0, implicit $x1 - ; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp - ; COMMON: RET_ReallyLR + ; On Darwin, everything is passed on the stack. Since the caller has no stack, + ; we don't tail call. + ; DARWIN-LABEL: name: test_varargs + ; DARWIN: bb.1 (%ir-block.0): + ; DARWIN: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 + ; DARWIN: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00 + ; DARWIN: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12 + ; DARWIN: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp + ; DARWIN: $w0 = COPY [[C]](s32) + ; DARWIN: $d0 = COPY [[C1]](s64) + ; DARWIN: $x1 = COPY [[C2]](s64) + ; DARWIN: BL @varargs, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $d0, implicit $x1 + ; DARWIN: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp + ; DARWIN: RET_ReallyLR + + ; Windows uses registers, so we don't need to worry about using the stack. + ; WINDOWS-LABEL: name: test_varargs + ; WINDOWS: bb.1 (%ir-block.0): + ; WINDOWS: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 + ; WINDOWS: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00 + ; WINDOWS: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12 + ; WINDOWS: $w0 = COPY [[C]](s32) + ; WINDOWS: $d0 = COPY [[C1]](s64) + ; WINDOWS: $x1 = COPY [[C2]](s64) + ; WINDOWS: TCRETURNdi @varargs, 0, csr_aarch64_aapcs, implicit $sp, implicit $w0, implicit $d0, implicit $x1 tail call void(i32, double, i64, ...) @varargs(i32 42, double 1.0, i64 12) ret void }