diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp index f4f3b261bf5..a827fd9de19 100644 --- a/lib/Target/ARM/ARMCallLowering.cpp +++ b/lib/Target/ARM/ARMCallLowering.cpp @@ -53,11 +53,27 @@ namespace { struct OutgoingValueHandler : public CallLowering::ValueHandler { OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstrBuilder &MIB, CCAssignFn *AssignFn) - : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {} + : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB), StackSize(0) {} unsigned getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO) override { - llvm_unreachable("Don't know how to get a stack address yet"); + // FIXME: Support smaller sizes (which may require extensions). + assert((Size == 4 || Size == 8) && "Unsupported size"); + + LLT p0 = LLT::pointer(0, 32); + LLT s32 = LLT::scalar(32); + unsigned SPReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildCopy(SPReg, ARM::SP); + + unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); + MIRBuilder.buildConstant(OffsetReg, Offset); + + unsigned AddrReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); + + MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + StackSize = std::max(StackSize, Size + Offset); + return AddrReg; } void assignValueToReg(unsigned ValVReg, unsigned PhysReg, @@ -75,7 +91,12 @@ struct OutgoingValueHandler : public CallLowering::ValueHandler { void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, MachinePointerInfo &MPO, CCValAssign &VA) override { - llvm_unreachable("Don't know how to assign a value to an address yet"); + // FIXME: Support smaller sizes (which may require extensions). + assert((Size == 4 || Size == 8) && "Unsupported size"); + + auto MMO = MIRBuilder.getMF().getMachineMemOperand( + MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0); + MIRBuilder.buildStore(ValVReg, Addr, *MMO); } unsigned assignCustomValue(const CallLowering::ArgInfo &Arg, @@ -110,6 +131,7 @@ struct OutgoingValueHandler : public CallLowering::ValueHandler { } MachineInstrBuilder &MIB; + uint64_t StackSize; }; } // End anonymous namespace. @@ -352,9 +374,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (MF.getSubtarget().genLongCalls()) return false; - MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN) - .addImm(0) - .add(predOps(ARMCC::AL)); + auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN); // FIXME: This is the calling convention of the caller - we should use the // calling convention of the callee instead. @@ -397,8 +417,12 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return false; } + // We now know the size of the stack - update the ADJCALLSTACKDOWN + // accordingly. + CallSeqStart.addImm(ArgHandler.StackSize).add(predOps(ARMCC::AL)); + MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP) - .addImm(0) + .addImm(ArgHandler.StackSize) .addImm(0) .add(predOps(ARMCC::AL)); diff --git a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index 31e15bc8fcc..c7a5a6cb67b 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -359,22 +359,51 @@ entry: ret void } -declare arm_aapcscc i32* @simple_params_target(i32, i32*) +declare arm_aapcscc i32* @simple_reg_params_target(i32, i32*) -define arm_aapcscc i32* @test_call_simple_params(i32 *%a, i32 %b) { -; CHECK-LABEL: name: test_call_simple_params +define arm_aapcscc i32* @test_call_simple_reg_params(i32 *%a, i32 %b) { +; CHECK-LABEL: name: test_call_simple_reg_params ; CHECK-DAG: [[AVREG:%[0-9]+]](p0) = COPY %r0 ; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %r1 ; CHECK: ADJCALLSTACKDOWN 0, 14, _, implicit-def %sp, implicit %sp ; CHECK-DAG: %r0 = COPY [[BVREG]] ; CHECK-DAG: %r1 = COPY [[AVREG]] -; CHECK: BLX @simple_params_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0 +; CHECK: BLX @simple_reg_params_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0 ; CHECK: [[RVREG:%[0-9]+]](p0) = COPY %r0 ; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp ; CHECK: %r0 = COPY [[RVREG]] ; CHECK: BX_RET 14, _, implicit %r0 entry: - %r = notail call arm_aapcscc i32 *@simple_params_target(i32 %b, i32 *%a) + %r = notail call arm_aapcscc i32 *@simple_reg_params_target(i32 %b, i32 *%a) + ret i32 *%r +} + +declare arm_aapcscc i32* @simple_stack_params_target(i32, i32*, i32, i32*, i32, i32*) + +define arm_aapcscc i32* @test_call_simple_stack_params(i32 *%a, i32 %b) { +; CHECK-LABEL: name: test_call_simple_stack_params +; CHECK-DAG: [[AVREG:%[0-9]+]](p0) = COPY %r0 +; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %r1 +; CHECK: ADJCALLSTACKDOWN 8, 14, _, 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) +; 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) +; CHECK: BLX @simple_stack_params_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0 +; CHECK: [[RVREG:%[0-9]+]](p0) = COPY %r0 +; CHECK: ADJCALLSTACKUP 8, 0, 14, _, implicit-def %sp, implicit %sp +; CHECK: %r0 = COPY [[RVREG]] +; CHECK: BX_RET 14, _, implicit %r0 +entry: + %r = notail call arm_aapcscc i32 *@simple_stack_params_target(i32 %b, i32 *%a, i32 %b, i32 *%a, i32 %b, i32 *%a) ret i32 *%r } @@ -423,7 +452,7 @@ entry: ret double %r } -declare arm_aapcscc double @aapcscc_fp_target(float, double) +declare arm_aapcscc double @aapcscc_fp_target(float, double, float, double) define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) { ; CHECK-LABEL: name: test_call_aapcs_fp_params @@ -432,19 +461,27 @@ define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) { ; LITTLE-DAG: [[AVREG:%[0-9]+]](s64) = G_SEQUENCE [[A1]](s32), 0, [[A2]](s32), 32 ; BIG-DAG: [[AVREG:%[0-9]+]](s64) = G_SEQUENCE [[A2]](s32), 0, [[A1]](s32), 32 ; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %r2 -; CHECK: ADJCALLSTACKDOWN 0, 14, _, implicit-def %sp, implicit %sp +; CHECK: ADJCALLSTACKDOWN 16, 14, _, implicit-def %sp, implicit %sp ; CHECK-DAG: %r0 = COPY [[BVREG]] ; CHECK-DAG: [[A1:%[0-9]+]](s32), [[A2:%[0-9]+]](s32) = G_EXTRACT [[AVREG]](s64), 0, 32 ; LITTLE-DAG: %r2 = COPY [[A1]] ; LITTLE-DAG: %r3 = COPY [[A2]] ; BIG-DAG: %r2 = COPY [[A2]] ; BIG-DAG: %r3 = COPY [[A1]] +; 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) +; CHECK: [[SP2:%[0-9]+]](p0) = COPY %sp +; CHECK: [[OFF2:%[0-9]+]](s32) = G_CONSTANT i32 8 +; CHECK: [[FI2:%[0-9]+]](p0) = G_GEP [[SP2]], [[OFF2]](s32) +; CHECK: G_STORE [[AVREG]](s64), [[FI2]](p0) ; CHECK: BLX @aapcscc_fp_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1 ; CHECK-DAG: [[R1:%[0-9]+]](s32) = COPY %r0 ; CHECK-DAG: [[R2:%[0-9]+]](s32) = COPY %r1 ; LITTLE: [[RVREG:%[0-9]+]](s64) = G_SEQUENCE [[R1]](s32), 0, [[R2]](s32), 32 ; BIG: [[RVREG:%[0-9]+]](s64) = G_SEQUENCE [[R2]](s32), 0, [[R1]](s32), 32 -; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp +; CHECK: ADJCALLSTACKUP 16, 0, 14, _, implicit-def %sp, implicit %sp ; CHECK: [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32) = G_EXTRACT [[RVREG]](s64), 0, 32 ; LITTLE-DAG: %r0 = COPY [[R1]] ; LITTLE-DAG: %r1 = COPY [[R2]] @@ -452,6 +489,6 @@ define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) { ; BIG-DAG: %r1 = COPY [[R1]] ; CHECK: BX_RET 14, _, implicit %r0, implicit %r1 entry: - %r = notail call arm_aapcscc double @aapcscc_fp_target(float %b, double %a) + %r = notail call arm_aapcscc double @aapcscc_fp_target(float %b, double %a, float %b, double %a) ret double %r }