OSDN Git Service

[ARM GlobalISel] Allow calls to varargs functions
authorDiana Picus <diana.picus@linaro.org>
Thu, 17 Jan 2019 10:11:55 +0000 (10:11 +0000)
committerDiana Picus <diana.picus@linaro.org>
Thu, 17 Jan 2019 10:11:55 +0000 (10:11 +0000)
Allow varargs functions to be called, both in arm and thumb mode. This
boils down to choosing the correct calling convention, which we can
easily test by making sure arm_aapcscc is used instead of
arm_aapcs_vfpcc when the callee is variadic.

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

lib/Target/ARM/ARMCallLowering.cpp
test/CodeGen/ARM/GlobalISel/arm-unsupported.ll
test/CodeGen/ARM/GlobalISel/irtranslator-varargs-lowering.ll [new file with mode: 0644]

index 8e80c32..a64544c 100644 (file)
@@ -561,13 +561,14 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
 
   MIB.addRegMask(TRI->getCallPreservedMask(MF, CallConv));
 
+  bool IsVarArg = false;
   SmallVector<ArgInfo, 8> ArgInfos;
   for (auto Arg : OrigArgs) {
     if (!isSupportedType(DL, TLI, Arg.Ty))
       return false;
 
     if (!Arg.IsFixed)
-      return false;
+      IsVarArg = true;
 
     if (Arg.Flags.isByVal())
       return false;
@@ -581,7 +582,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
       MIRBuilder.buildUnmerge(Regs, Arg.Reg);
   }
 
-  auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false);
+  auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, IsVarArg);
   OutgoingValueHandler ArgHandler(MIRBuilder, MRI, MIB, ArgAssignFn);
   if (!handleAssignments(MIRBuilder, ArgInfos, ArgHandler))
     return false;
@@ -600,7 +601,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
                         SplitRegs.push_back(Reg);
                       });
 
-    auto RetAssignFn = TLI.CCAssignFnForReturn(CallConv, /*IsVarArg=*/false);
+    auto RetAssignFn = TLI.CCAssignFnForReturn(CallConv, IsVarArg);
     CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn);
     if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler))
       return false;
index 5011533..e7df312 100644 (file)
@@ -83,13 +83,6 @@ define void @test_vararg_definition(i32 %a, ...) {
   ret void
 }
 
-define void @test_vararg_call(i32 %a) {
-; CHECK: remark: {{.*}} unable to translate instruction: call
-; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_call
-  call void(i32, ...) @test_vararg_definition(i32 %a, i32 %a, i32 %a)
-  ret void
-}
-
 define i32 @test_thumb(i32 %a) #0 {
 ; CHECK: remark: {{.*}} unable to lower arguments: i32 (i32)*
 ; CHECK-LABEL: warning: Instruction selection used fallback path for test_thumb
diff --git a/test/CodeGen/ARM/GlobalISel/irtranslator-varargs-lowering.ll b/test/CodeGen/ARM/GlobalISel/irtranslator-varargs-lowering.ll
new file mode 100644 (file)
index 0000000..351594d
--- /dev/null
@@ -0,0 +1,86 @@
+; RUN: llc -mtriple arm-unknown -mattr=+vfp2,+v6t2 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ARM
+; RUN: llc -mtriple thumb-unknown -mattr=+vfp2,+v6t2 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=THUMB
+
+declare arm_aapcscc i32 @int_varargs_target(i32, ...)
+
+define arm_aapcscc i32 @test_call_to_varargs_with_ints(i32 *%a, i32 %b) {
+; CHECK-LABEL: name: test_call_to_varargs_with_ints
+; CHECK-DAG: [[AVREG:%[0-9]+]]:_(p0) = COPY $r0
+; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r1
+; CHECK: ADJCALLSTACKDOWN 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK-DAG: $r0 = COPY [[BVREG]]
+; CHECK-DAG: $r1 = COPY [[AVREG]]
+; CHECK-DAG: $r2 = COPY [[BVREG]]
+; CHECK-DAG: $r3 = COPY [[AVREG]]
+; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp
+; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_GEP [[SP1]], [[OFF1]](s32)
+; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0){{.*}}store 4
+; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp
+; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_GEP [[SP2]], [[OFF2]](s32)
+; CHECK: G_STORE [[AVREG]](p0), [[FI2]](p0){{.*}}store 4
+; ARM: BL @int_varargs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0
+; THUMB: tBL 14, $noreg, @int_varargs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0
+; CHECK: [[RVREG:%[0-9]+]]:_(s32) = COPY $r0
+; CHECK: ADJCALLSTACKUP 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK: $r0 = COPY [[RVREG]]
+; ARM: BX_RET 14, $noreg, implicit $r0
+; THUMB: tBX_RET 14, $noreg, implicit $r0
+entry:
+  %r = notail call arm_aapcscc i32(i32, ...) @int_varargs_target(i32 %b, i32 *%a, i32 %b, i32 *%a, i32 %b, i32 *%a)
+  ret i32 %r
+}
+
+declare arm_aapcs_vfpcc float @float_varargs_target(float, double, ...)
+
+define arm_aapcs_vfpcc float @test_call_to_varargs_with_floats(float %a, double %b) {
+; CHECK-LABEL: name: test_call_to_varargs_with_floats
+; CHECK-DAG: [[AVREG:%[0-9]+]]:_(s32) = COPY $s0
+; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s64) = COPY $d1
+; CHECK: ADJCALLSTACKDOWN 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK-DAG: $r0 = COPY [[AVREG]]
+; CHECK-DAG: [[B1:%[0-9]+]]:_(s32), [[B2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BVREG]](s64)
+; CHECK-DAG: $r2 = COPY [[B1]]
+; CHECK-DAG: $r3 = COPY [[B2]]
+; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp
+; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_GEP [[SP1]], [[OFF1]](s32)
+; CHECK: G_STORE [[BVREG]](s64), [[FI1]](p0){{.*}}store 8
+; ARM: BL @float_varargs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0
+; THUMB: tBL 14, $noreg, @float_varargs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0
+; CHECK: [[RVREG:%[0-9]+]]:_(s32) = COPY $r0
+; CHECK: ADJCALLSTACKUP 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK: $s0 = COPY [[RVREG]]
+; ARM: BX_RET 14, $noreg, implicit $s0
+; THUMB: tBX_RET 14, $noreg, implicit $s0
+entry:
+  %r = notail call arm_aapcs_vfpcc float(float, double, ...) @float_varargs_target(float %a, double %b, double %b)
+  ret float %r
+}
+
+define arm_aapcs_vfpcc float @test_indirect_call_to_varargs(float (float, double, ...) *%fptr, float %a, double %b) {
+; CHECK-LABEL: name: test_indirect_call_to_varargs
+; CHECK-DAG: [[FPTRVREG:%[0-9]+]]:gpr(p0) = COPY $r0
+; CHECK-DAG: [[AVREG:%[0-9]+]]:_(s32) = COPY $s0
+; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s64) = COPY $d1
+; CHECK: ADJCALLSTACKDOWN 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK-DAG: $r0 = COPY [[AVREG]]
+; CHECK-DAG: [[B1:%[0-9]+]]:_(s32), [[B2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BVREG]](s64)
+; CHECK-DAG: $r2 = COPY [[B1]]
+; CHECK-DAG: $r3 = COPY [[B2]]
+; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp
+; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_GEP [[SP1]], [[OFF1]](s32)
+; CHECK: G_STORE [[BVREG]](s64), [[FI1]](p0){{.*}}store 8
+; ARM: BLX [[FPTRVREG]](p0), csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0
+; THUMB: tBLXr 14, $noreg, [[FPTRVREG]](p0), csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0
+; CHECK: [[RVREG:%[0-9]+]]:_(s32) = COPY $r0
+; CHECK: ADJCALLSTACKUP 8, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK: $s0 = COPY [[RVREG]]
+; ARM: BX_RET 14, $noreg, implicit $s0
+; THUMB: tBX_RET 14, $noreg, implicit $s0
+entry:
+  %r = notail call arm_aapcs_vfpcc float(float, double, ...) %fptr(float %a, double %b, double %b)
+  ret float %r
+}