]> granicus.if.org Git - llvm/commitdiff
[AArch64][GlobalISel] Add support for sibcalling callees with varargs
authorJessica Paquette <jpaquette@apple.com>
Fri, 13 Sep 2019 16:10:19 +0000 (16:10 +0000)
committerJessica Paquette <jpaquette@apple.com>
Fri, 13 Sep 2019 16:10:19 +0000 (16:10 +0000)
This adds support for tail calling callees with varargs, equivalent to how it
is done in AArch64ISelLowering.

This only works for sibling calls, and does not add the necessary support for
musttail with varargs. (See r345641 for equivalent ISelLowering support.) This
should be implemented when we stop falling back on musttail.

Update call-translator-tail-call.ll to show that we can now tail call varargs.

Differential Revision: https://reviews.llvm.org/D67518

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@371868 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64CallLowering.cpp
test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll

index a3a212c5128577a50dcf708158917052b574e603..1e3d6e5483f59d4ffec3b36aca03f4e7d7a7fd6d 100644 (file)
@@ -514,8 +514,20 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable(
   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 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization(
     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 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization(
   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 97252825f79313725c57c99a34c5009621a805dd..5be29e04512fb2f9821bacecd26d80e4defd9891 100644 (file)
@@ -75,22 +75,33 @@ define i32 @test_nonvoid_ret() {
   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
 }