diff --git a/llvm/lib/Target/M68k/GlSel/M68kCallLowering.h b/llvm/lib/Target/M68k/GlSel/M68kCallLowering.h --- a/llvm/lib/Target/M68k/GlSel/M68kCallLowering.h +++ b/llvm/lib/Target/M68k/GlSel/M68kCallLowering.h @@ -43,6 +43,29 @@ bool enableBigEndian() const override; }; +struct M68kIncomingValueHandler : public CallLowering::IncomingValueHandler { + M68kIncomingValueHandler(MachineIRBuilder &MIRBuilder, + MachineRegisterInfo &MRI) + : CallLowering::IncomingValueHandler(MIRBuilder, MRI) {} + + uint64_t StackUsed; + +private: + void assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign &VA) override; + + void assignValueToAddress(Register ValVReg, Register Addr, uint64_t Size, + MachinePointerInfo &MPO, CCValAssign &VA) override; + + Register getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) override; +}; + +struct FormalArgHandler : public M68kIncomingValueHandler { + FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) + : M68kIncomingValueHandler(MIRBuilder, MRI) {} +}; } // end namespace llvm 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 @@ -15,12 +15,17 @@ #include "M68kCallLowering.h" #include "M68kISelLowering.h" #include "M68kInstrInfo.h" +#include "M68kSubtarget.h" +#include "M68kTargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/TargetCallingConv.h" + using namespace llvm; M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI) : CallLowering(&TLI) {} - bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs, FunctionLoweringInfo &FLI, @@ -36,11 +41,63 @@ const Function &F, ArrayRef> VRegs, FunctionLoweringInfo &FLI) const { + MachineFunction &MF = MIRBuilder.getMF(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + const auto &DL = F.getParent()->getDataLayout(); + auto &TLI = *getTLI(); - if (F.arg_empty()) - return true; + SmallVector SplitArgs; + unsigned I = 0; + for (const auto &Arg : F.args()) { + ArgInfo OrigArg{VRegs[I], Arg.getType()}; + setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); + splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); + ++I; + } - return false; + CCAssignFn *AssignFn = + TLI.getCCAssignFnForCall(F.getCallingConv(), false, F.isVarArg()); + IncomingValueAssigner ArgAssigner(AssignFn); + FormalArgHandler ArgHandler(MIRBuilder, MRI); + return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, + MIRBuilder, F.getCallingConv(), + F.isVarArg()); +} + +void M68kIncomingValueHandler::assignValueToReg(Register ValVReg, + Register PhysReg, + CCValAssign &VA) { + MIRBuilder.getMRI()->addLiveIn(PhysReg); + MIRBuilder.getMBB().addLiveIn(PhysReg); + IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); +} + +void M68kIncomingValueHandler::assignValueToAddress(Register ValVReg, + Register Addr, + uint64_t Size, + MachinePointerInfo &MPO, + CCValAssign &VA) { + MachineFunction &MF = MIRBuilder.getMF(); + auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, + inferAlignFromPtrInfo(MF, MPO)); + MIRBuilder.buildLoad(ValVReg, Addr, *MMO); +} + +Register M68kIncomingValueHandler::getStackAddress(uint64_t Size, + int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) { + auto &MFI = MIRBuilder.getMF().getFrameInfo(); + const bool IsImmutable = !Flags.isByVal(); + int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); + MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + + // Build Frame Index + llvm::LLT FramePtr = LLT::pointer( + 0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits()); + MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI); + StackUsed = std::max(StackUsed, Size + Offset); + return AddrReg.getReg(0); } bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 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,6 +171,9 @@ EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; + CCAssignFn *getCCAssignFnForCall(CallingConv::ID CC, bool Return, + bool IsVarArg) const; + private: unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG) const; 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 @@ -3412,3 +3412,9 @@ return NULL; } } + +CCAssignFn *M68kTargetLowering::getCCAssignFnForCall(CallingConv::ID CC, + bool Return, + bool IsVarArg) const { + 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 @@ -1,7 +1,177 @@ ; RUN: llc -mtriple=m68k -global-isel -stop-after=irtranslator < %s | FileCheck %s + ; CHECK: name: noArgRetVoid ; CHECK: RTS define void @noArgRetVoid() { ret void } + +%struct.A = type { i8, float, i32, i32, i32 } + +define void @test_arg_lowering1(i8 %x, i8 %y) { + ; CHECK-LABEL: name: test_arg_lowering1 + ; 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_TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD1]](s32) + ; CHECK: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I2]](p0) + ; CHECK: [[G_TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD2]](s32) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering2(i16 %x, i16 %y) { + ; CHECK-LABEL: name: test_arg_lowering2 + ; 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_TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[G_LOAD1]](s32) + ; CHECK: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I2]](p0) + ; CHECK: [[G_TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[G_LOAD2]](s32) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering3(i32 %x, i32 %y) { + ; CHECK-LABEL: name: test_arg_lowering3 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: [[G_F_I1:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: {{%.*}} G_LOAD [[G_F_I1]](p0) + ; CHECK: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: {{%.*}} G_LOAD [[G_F_I2]](p0) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering_vector(<5 x i8> %x) { + ; CHECK-LABEL: name: test_arg_lowering_vector + ; 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_F_I3:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I3]](p0) + ; CHECK: [[G_F_I4:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD4:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I4]](p0) + ; CHECK: [[G_F_I5:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD5:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I5]](p0) + ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<5 x s32>) = G_BUILD_VECTOR [[G_LOAD1]](s32), [[G_LOAD2]](s32), [[G_LOAD3]](s32), [[G_LOAD4]](s32), [[G_LOAD5]](s32) + ; CHECK: [[G_TRUNC:%[0-9]+]]:_(<5 x s8>) = G_TRUNC [[BUILD_VECTOR]](<5 x s32>) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering_array([5 x i8] %x) { + ; CHECK-LABEL: name: test_arg_lowering_array + ; 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: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I2]](p0) + ; CHECK: [[G_TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD2]](s32) + ; CHECK: [[G_F_I3:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I3]](p0) + ; CHECK: [[G_TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD3]](s32) + ; CHECK: [[G_F_I4:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD4:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I4]](p0) + ; CHECK: [[G_TRUNC4:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD4]](s32) + ; CHECK: [[G_F_I5:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD5:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I5]](p0) + ; CHECK: [[G_TRUNC5:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD5]](s32) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering_double(double %x) { + ; CHECK-LABEL: name: test_arg_lowering_double + ; 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: RTS + ret void +} + +define void @test_arg_lowering_float(float %x) { + ; CHECK-LABEL: name: test_arg_lowering_float + ; 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: RTS + ret void +} + +define void @test_arg_lowering_multiple(i1 %a, i8 %b, i16 %c, i32 %d, i64 %e, i128 %f){ + ; CHECK-LABEL: name: test_arg_lowering_multiple + ; 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]+]]:_(s1) = G_TRUNC [[G_LOAD1]](s32) + ; CHECK: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I2]](p0) + ; CHECK: [[G_TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[G_LOAD2]](s32) + ; CHECK: [[G_F_I3:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I3]](p0) + ; CHECK: [[G_TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[G_LOAD3]](s32) + ; CHECK: [[G_F_I4:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD4:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I4]](p0) + ; CHECK: [[G_F_I5:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD5:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I5]](p0) + ; CHECK: [[G_F_I6:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD6:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I6]](p0) + ; CHECK: [[G_MERGE_VAL:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[G_LOAD5]](s32), [[G_LOAD6]](s32) + ; CHECK: [[G_F_I7:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD7:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I7]](p0) + ; CHECK: [[G_F_I8:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD8:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I8]](p0) + ; CHECK: [[G_F_I9:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD9:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I9]](p0) + ; CHECK: [[G_F_I10:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD10:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I10]](p0) + ; CHECK: [[G_MERGE_VAL:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[G_LOAD7]](s32), [[G_LOAD8]](s32), [[G_LOAD9]](s32), [[G_LOAD10]](s32) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering_ptr(i32* %x) { + ; CHECK-LABEL: name: test_arg_lowering_ptr + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: [[G_F_I1:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[G_F_I1]](p0) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering_float_ptr(float* %x) { + ; CHECK-LABEL: name: test_arg_lowering_float_ptr + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: [[G_F_I1:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[G_F_I1]](p0) + ; CHECK: RTS + ret void +} + +define void @test_arg_lowering_struct(%struct.A %a) #0 { + ; CHECK-LABEL: name: test_arg_lowering_struct + ; 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: [[G_F_I2:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I2]](p0) + ; CHECK: [[G_F_I3:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I3]](p0) + ; CHECK: [[G_F_I4:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD4:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I4]](p0) + ; CHECK: [[G_F_I5:%[0-9]+]]:_(p0) = G_FRAME_INDEX + ; CHECK: [[G_LOAD5:%[0-9]+]]:_(s32) = G_LOAD [[G_F_I5]](p0) + ; CHECK: RTS + ret void +}