diff --git a/llvm/lib/Target/M68k/GlSel/M68kCallLowering.cpp b/llvm/lib/Target/M68k/GlSel/M68kCallLowering.cpp --- a/llvm/lib/Target/M68k/GlSel/M68kCallLowering.cpp +++ b/llvm/lib/Target/M68k/GlSel/M68kCallLowering.cpp @@ -26,15 +26,59 @@ M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI) : CallLowering(&TLI) {} + +struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler { + OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder MIB) + : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {} + + void assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign &VA) override { + MIB.addUse(PhysReg, RegState::Implicit); + Register ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildCopy(PhysReg, ExtReg); + } + + void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, + MachinePointerInfo &MPO, CCValAssign &VA) override { + llvm_unreachable("unimplemented"); + } + + Register getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) override { + llvm_unreachable("unimplemented"); + } + + MachineInstrBuilder MIB; +}; bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs, FunctionLoweringInfo &FLI, Register SwiftErrorVReg) const { - if (Val) - return false; - MIRBuilder.buildInstr(M68k::RTS); - return true; + auto MIB = MIRBuilder.buildInstrNoInsert(M68k::RTS); + bool Success = true; + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = MF.getFunction(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + const M68kTargetLowering &TLI = *getTLI(); + CCAssignFn *AssignFn = + TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg()); + auto &DL = F.getParent()->getDataLayout(); + if (!VRegs.empty()) { + SmallVector SplitArgs; + ArgInfo OrigArg{VRegs, Val->getType()}; + setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); + splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); + OutgoingValueAssigner ArgAssigner(AssignFn); + OutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); + Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, + MIRBuilder, F.getCallingConv(), + F.isVarArg()); + } + MIRBuilder.insertInstr(MIB); + return Success; } bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, @@ -56,7 +100,7 @@ } CCAssignFn *AssignFn = - TLI.getCCAssignFnForCall(F.getCallingConv(), false, F.isVarArg()); + TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg()); IncomingValueAssigner ArgAssigner(AssignFn); FormalArgHandler ArgHandler(MIRBuilder, MRI); return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, diff --git a/llvm/lib/Target/M68k/M68kISelLowering.h b/llvm/lib/Target/M68k/M68kISelLowering.h --- a/llvm/lib/Target/M68k/M68kISelLowering.h +++ b/llvm/lib/Target/M68k/M68kISelLowering.h @@ -171,8 +171,8 @@ EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; - CCAssignFn *getCCAssignFnForCall(CallingConv::ID CC, bool Return, - bool IsVarArg) const; + CCAssignFn *getCCAssignFn(CallingConv::ID CC, bool Return, + bool IsVarArg) const; private: unsigned GetAlignedArgumentStackSize(unsigned StackSize, diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -3413,8 +3413,10 @@ } } -CCAssignFn *M68kTargetLowering::getCCAssignFnForCall(CallingConv::ID CC, - bool Return, - bool IsVarArg) const { - return CC_M68k_C; +CCAssignFn *M68kTargetLowering::getCCAssignFn(CallingConv::ID CC, bool Return, + bool IsVarArg) const { + if (Return) + return RetCC_M68k_C; + else + return CC_M68k_C; } diff --git a/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll b/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll --- a/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll +++ b/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll @@ -175,3 +175,39 @@ ; CHECK: RTS ret void } + +define i8 @test_ret1(i8 %a) { + ; CHECK-LABEL: name: test_ret1 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: [[G_F_I1:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I1]](p0) + ; CHECK: [[G_TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD1]](s32) + ; CHECK: $bd0 = COPY [[G_TRUNC1]](s8) + ; CHECK: RTS implicit $bd0 + ret i8 %a +} + +define i32 @test_ret2(i32 %a) { + ; CHECK-LABEL: name: test_ret2 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: [[G_F_I1:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I1]](p0) + ; CHECK: $d0 = COPY [[G_LOAD1]](s32) + ; CHECK: RTS implicit $d0 + ret i32 %a +} + +define i64 @test_ret3(i64 %a) { + ; CHECK-LABEL: name: test_ret3 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: [[G_F_I1:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I1]](p0) + ; CHECK: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I2]](p0) + ; CHECK: [[G_MERGE_VAL:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[G_LOAD1]](s32), [[G_LOAD2]](s32) + ; CHECK: [[G_UNMERGE_VAL1:%[0-9]+]]:_(s32), [[G_UNMERGE_VAL2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[G_MERGE_VAL]](s64) + ; CHECK: $d0 = COPY [[G_UNMERGE_VAL1]](s32) + ; CHECK: $d1 = COPY [[G_UNMERGE_VAL2]](s32) + ; CHECK: RTS implicit $d0, implicit $d1 + ret i64 %a +}