From b99810417e18d64b0db36db2dddb7fd9d83f0bcd Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Thu, 17 Jan 2019 10:11:55 +0000 Subject: [PATCH] [ARM GlobalISel] Allow calls to varargs functions 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. llvm-svn: 351424 --- lib/Target/ARM/ARMCallLowering.cpp | 7 +- .../CodeGen/ARM/GlobalISel/arm-unsupported.ll | 7 -- .../irtranslator-varargs-lowering.ll | 86 +++++++++++++++++++ 3 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 test/CodeGen/ARM/GlobalISel/irtranslator-varargs-lowering.ll diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp index 8e80c32bcf8..a64544c20d1 100644 --- a/lib/Target/ARM/ARMCallLowering.cpp +++ b/lib/Target/ARM/ARMCallLowering.cpp @@ -561,13 +561,14 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, MIB.addRegMask(TRI->getCallPreservedMask(MF, CallConv)); + bool IsVarArg = false; SmallVector 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; diff --git a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll index 501153343ba..e7df3121037 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -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 index 00000000000..351594d1fc2 --- /dev/null +++ b/test/CodeGen/ARM/GlobalISel/irtranslator-varargs-lowering.ll @@ -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 +}