| //===-- M68kCallLowering.cpp - Call lowering --------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \file |
| /// This file implements the lowering of LLVM calls to machine code calls for |
| /// GlobalISel. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #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/MachineFrameInfo.h" |
| #include "llvm/CodeGen/TargetCallingConv.h" |
| |
| using namespace llvm; |
| |
| M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI) |
| : CallLowering(&TLI) {} |
| |
| 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<M68kSubtarget>()) {} |
| |
| 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 { |
| 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 { |
| 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<Register> VRegs, |
| FunctionLoweringInfo &FLI, |
| Register SwiftErrorVReg) const { |
| |
| 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<M68kTargetLowering>(); |
| CCAssignFn *AssignFn = |
| TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg()); |
| auto &DL = F.getParent()->getDataLayout(); |
| if (!VRegs.empty()) { |
| SmallVector<ArgInfo, 8> SplitArgs; |
| ArgInfo OrigArg{VRegs, Val->getType(), 0}; |
| setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); |
| splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); |
| OutgoingValueAssigner ArgAssigner(AssignFn); |
| M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); |
| Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, |
| MIRBuilder, F.getCallingConv(), |
| F.isVarArg()); |
| } |
| MIRBuilder.insertInstr(MIB); |
| return Success; |
| } |
| |
| bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, |
| const Function &F, |
| ArrayRef<ArrayRef<Register>> VRegs, |
| FunctionLoweringInfo &FLI) const { |
| MachineFunction &MF = MIRBuilder.getMF(); |
| MachineRegisterInfo &MRI = MF.getRegInfo(); |
| const auto &DL = F.getParent()->getDataLayout(); |
| auto &TLI = *getTLI<M68kTargetLowering>(); |
| |
| SmallVector<ArgInfo, 8> SplitArgs; |
| unsigned I = 0; |
| for (const auto &Arg : F.args()) { |
| ArgInfo OrigArg{VRegs[I], Arg.getType(), I}; |
| setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); |
| splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); |
| ++I; |
| } |
| |
| CCAssignFn *AssignFn = |
| TLI.getCCAssignFn(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, |
| LLT MemTy, |
| MachinePointerInfo &MPO, |
| CCValAssign &VA) { |
| MachineFunction &MF = MIRBuilder.getMF(); |
| auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, |
| 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); |
| } |
| |
| 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 { |
| MachineFunction &MF = MIRBuilder.getMF(); |
| Function &F = MF.getFunction(); |
| MachineRegisterInfo &MRI = MF.getRegInfo(); |
| auto &DL = F.getParent()->getDataLayout(); |
| const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>(); |
| const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>(); |
| const TargetInstrInfo &TII = *STI.getInstrInfo(); |
| const M68kRegisterInfo *TRI = STI.getRegisterInfo(); |
| |
| SmallVector<ArgInfo, 8> OutArgs; |
| for (auto &OrigArg : Info.OrigArgs) |
| splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv); |
| |
| SmallVector<ArgInfo, 8> 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(Info.CallConv, false, Info.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(Info.CallConv, true, Info.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; } |