Index: llvm/lib/Target/M68k/GISel/M68kCallLowering.h =================================================================== --- llvm/lib/Target/M68k/GISel/M68kCallLowering.h +++ llvm/lib/Target/M68k/GISel/M68kCallLowering.h @@ -22,6 +22,7 @@ namespace llvm { class M68kTargetLowering; +class MachineInstrBuilder; class M68kCallLowering : public CallLowering { // TODO: We are only supporting return instruction with no value at this time @@ -67,6 +68,17 @@ : M68kIncomingValueHandler(MIRBuilder, MRI) {} }; +struct CallReturnHandler : public M68kIncomingValueHandler { + CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder &MIB) + : M68kIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} + +private: + void assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign VA) override; + + MachineInstrBuilder &MIB; +}; } // end namespace llvm #endif // LLVM_LIB_TARGET_M68K_GLSEL_M68KCALLLOWERING_H Index: llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp =================================================================== --- llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp +++ llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp @@ -27,10 +27,12 @@ M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI) : CallLowering(&TLI) {} -struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler { - OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, - MachineInstrBuilder MIB) - : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {} +struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler { + M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder MIB) + : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB), + DL(MIRBuilder.getMF().getDataLayout()), + STI(MIRBuilder.getMF().getSubtarget()) {} void assignValueToReg(Register ValVReg, Register PhysReg, CCValAssign VA) override { @@ -41,16 +43,29 @@ void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, MachinePointerInfo &MPO, CCValAssign &VA) override { - llvm_unreachable("unimplemented"); + MachineFunction &MF = MIRBuilder.getMF(); + Register ExtReg = extendRegister(ValVReg, VA); + + auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy, + inferAlignFromPtrInfo(MF, MPO)); + MIRBuilder.buildStore(ExtReg, Addr, *MMO); } Register getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO, ISD::ArgFlagsTy Flags) override { - llvm_unreachable("unimplemented"); + LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0)); + LLT SType = LLT::scalar(DL.getPointerSizeInBits(0)); + Register StackReg = STI.getRegisterInfo()->getStackRegister(); + auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0); + auto OffsetReg = MIRBuilder.buildConstant(SType, Offset); + auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); + MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + return AddrReg.getReg(0); } - MachineInstrBuilder MIB; + const DataLayout &DL; + const M68kSubtarget &STI; }; bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs, @@ -72,7 +87,7 @@ setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); OutgoingValueAssigner ArgAssigner(AssignFn); - OutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); + M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, MIRBuilder, F.getCallingConv(), F.isVarArg()); @@ -144,9 +159,74 @@ return AddrReg.getReg(0); } +void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign VA) { + MIB.addDef(PhysReg, RegState::Implicit); + MIRBuilder.buildCopy(ValVReg, PhysReg); +} + bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const { - return false; + MachineFunction &MF = MIRBuilder.getMF(); + Function &F = MF.getFunction(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + auto &DL = F.getParent()->getDataLayout(); + const M68kTargetLowering &TLI = *getTLI(); + const M68kSubtarget &STI = MF.getSubtarget(); + const TargetInstrInfo &TII = *STI.getInstrInfo(); + const M68kRegisterInfo *TRI = STI.getRegisterInfo(); + + SmallVector OutArgs; + for (auto &OrigArg : Info.OrigArgs) + splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv); + + SmallVector InArgs; + if (!Info.OrigRet.Ty->isVoidTy()) + splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv); + + unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); + auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown); + + unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq + : Info.Callee.isReg() ? M68k::CALLj + : M68k::CALLb; + + auto MIB = MIRBuilder.buildInstrNoInsert(Opc) + .add(Info.Callee) + .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); + + CCAssignFn *AssignFn = + TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg()); + OutgoingValueAssigner Assigner(AssignFn); + M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB); + if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder, + Info.CallConv, Info.IsVarArg)) + return false; + + if (Info.Callee.isReg()) + constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(), + *STI.getRegBankInfo(), *MIB, MIB->getDesc(), + Info.Callee, 0); + + MIRBuilder.insertInstr(MIB); + + if (!Info.OrigRet.Ty->isVoidTy()) { + CCAssignFn *RetAssignFn = + TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg()); + + OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn); + CallReturnHandler Handler(MIRBuilder, MRI, MIB); + if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder, + Info.CallConv, Info.IsVarArg)) + return false; + } + + CallSeqStart.addImm(Assigner.StackOffset).addImm(0); + + unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); + MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackOffset).addImm(0); + + return true; } bool M68kCallLowering::enableBigEndian() const { return true; } Index: llvm/test/CodeGen/M68k/GlobalISel/irtranslator-call.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/GlobalISel/irtranslator-call.ll @@ -0,0 +1,41 @@ +; RUN: llc -mtriple=m68k -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - 2>&1 | FileCheck %s + +; CHECK-LABEL: name: test_trivial_call +; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp +; CHECK: CALLb @trivial_callee, csr_std, implicit $sp +; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp +; CHECK: RTS +declare void @trivial_callee() +define void @test_trivial_call() { + call void @trivial_callee() + ret void +} + +; CHECK-LABEL: name: test_simple_return +; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp +; CHECK: CALLb @simple_return_callee, csr_std, implicit $sp, implicit-def $d0 +; CHECK: [[RES:%[0-9]+]]:_(s32) = COPY $d0 +; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp +; CHECK $d0 = COPY [[RES]] +; CHECK RTS implicit $d0 +declare i32 @simple_return_callee() +define i32 @test_simple_return() { + %res = call i32 @simple_return_callee() + ret i32 %res +} + +; CHECK-LABEL: name: test_simple_arg +; CHECK: [[ARG:%[0-9]+]]:_(s32) = G_CONSTANT i32 1048596 +; CHECK: ADJCALLSTACKDOWN 4, 0, implicit-def $sp, implicit-def $ccr, implicit $sp +; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp +; CHECK: [[OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 +; CHECK: [[PTR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFFSET]](s32) +; CHECK: G_STORE [[ARG]](s32), [[PTR]](p0) +; CHECK: CALLb @simple_arg_callee, csr_std, implicit $sp +; CHECK: ADJCALLSTACKUP 4, 0, implicit-def $sp, implicit-def $ccr, implicit $sp +; CHECK: RTS +declare void @simple_arg_callee(i32 %0) +define void @test_simple_arg() { + call void @simple_arg_callee(i32 1048596) + ret void +}