diff options
Diffstat (limited to 'llvm/lib/Target/ARM')
-rw-r--r-- | llvm/lib/Target/ARM/ARMCallLowering.cpp | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/llvm/lib/Target/ARM/ARMCallLowering.cpp b/llvm/lib/Target/ARM/ARMCallLowering.cpp index f4f3b261bf5..a827fd9de19 100644 --- a/llvm/lib/Target/ARM/ARMCallLowering.cpp +++ b/llvm/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<ARMSubtarget>().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)); |