1 //===-- M68kCallLowering.cpp - Call lowering --------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 /// This file implements the lowering of LLVM calls to machine code calls for 11 /// GlobalISel. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "M68kCallLowering.h" 16 #include "M68kISelLowering.h" 17 #include "M68kInstrInfo.h" 18 #include "M68kSubtarget.h" 19 #include "M68kTargetMachine.h" 20 #include "llvm/CodeGen/CallingConvLower.h" 21 #include "llvm/CodeGen/GlobalISel/CallLowering.h" 22 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 23 #include "llvm/CodeGen/MachineFrameInfo.h" 24 #include "llvm/CodeGen/TargetCallingConv.h" 25 26 using namespace llvm; 27 28 M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI) 29 : CallLowering(&TLI) {} 30 31 struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler { 32 M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 33 MachineInstrBuilder MIB) 34 : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB), 35 DL(MIRBuilder.getMF().getDataLayout()), 36 STI(MIRBuilder.getMF().getSubtarget<M68kSubtarget>()) {} 37 38 void assignValueToReg(Register ValVReg, Register PhysReg, 39 CCValAssign VA) override { 40 MIB.addUse(PhysReg, RegState::Implicit); 41 Register ExtReg = extendRegister(ValVReg, VA); 42 MIRBuilder.buildCopy(PhysReg, ExtReg); 43 } 44 45 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 46 MachinePointerInfo &MPO, CCValAssign &VA) override { 47 MachineFunction &MF = MIRBuilder.getMF(); 48 Register ExtReg = extendRegister(ValVReg, VA); 49 50 auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy, 51 inferAlignFromPtrInfo(MF, MPO)); 52 MIRBuilder.buildStore(ExtReg, Addr, *MMO); 53 } 54 55 Register getStackAddress(uint64_t Size, int64_t Offset, 56 MachinePointerInfo &MPO, 57 ISD::ArgFlagsTy Flags) override { 58 LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0)); 59 LLT SType = LLT::scalar(DL.getPointerSizeInBits(0)); 60 Register StackReg = STI.getRegisterInfo()->getStackRegister(); 61 auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0); 62 auto OffsetReg = MIRBuilder.buildConstant(SType, Offset); 63 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); 64 MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 65 return AddrReg.getReg(0); 66 } 67 MachineInstrBuilder MIB; 68 const DataLayout &DL; 69 const M68kSubtarget &STI; 70 }; 71 bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 72 const Value *Val, ArrayRef<Register> VRegs, 73 FunctionLoweringInfo &FLI, 74 Register SwiftErrorVReg) const { 75 76 auto MIB = MIRBuilder.buildInstrNoInsert(M68k::RTS); 77 bool Success = true; 78 MachineFunction &MF = MIRBuilder.getMF(); 79 const Function &F = MF.getFunction(); 80 MachineRegisterInfo &MRI = MF.getRegInfo(); 81 const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>(); 82 CCAssignFn *AssignFn = 83 TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg()); 84 auto &DL = F.getParent()->getDataLayout(); 85 if (!VRegs.empty()) { 86 SmallVector<ArgInfo, 8> SplitArgs; 87 ArgInfo OrigArg{VRegs, Val->getType(), 0}; 88 setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); 89 splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 90 OutgoingValueAssigner ArgAssigner(AssignFn); 91 M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); 92 Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, 93 MIRBuilder, F.getCallingConv(), 94 F.isVarArg()); 95 } 96 MIRBuilder.insertInstr(MIB); 97 return Success; 98 } 99 100 bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 101 const Function &F, 102 ArrayRef<ArrayRef<Register>> VRegs, 103 FunctionLoweringInfo &FLI) const { 104 MachineFunction &MF = MIRBuilder.getMF(); 105 MachineRegisterInfo &MRI = MF.getRegInfo(); 106 const auto &DL = F.getParent()->getDataLayout(); 107 auto &TLI = *getTLI<M68kTargetLowering>(); 108 109 SmallVector<ArgInfo, 8> SplitArgs; 110 unsigned I = 0; 111 for (const auto &Arg : F.args()) { 112 ArgInfo OrigArg{VRegs[I], Arg.getType(), I}; 113 setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); 114 splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 115 ++I; 116 } 117 118 CCAssignFn *AssignFn = 119 TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg()); 120 IncomingValueAssigner ArgAssigner(AssignFn); 121 FormalArgHandler ArgHandler(MIRBuilder, MRI); 122 return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, 123 MIRBuilder, F.getCallingConv(), 124 F.isVarArg()); 125 } 126 127 void M68kIncomingValueHandler::assignValueToReg(Register ValVReg, 128 Register PhysReg, 129 CCValAssign VA) { 130 MIRBuilder.getMRI()->addLiveIn(PhysReg); 131 MIRBuilder.getMBB().addLiveIn(PhysReg); 132 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); 133 } 134 135 void M68kIncomingValueHandler::assignValueToAddress(Register ValVReg, 136 Register Addr, 137 LLT MemTy, 138 MachinePointerInfo &MPO, 139 CCValAssign &VA) { 140 MachineFunction &MF = MIRBuilder.getMF(); 141 auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, 142 inferAlignFromPtrInfo(MF, MPO)); 143 MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 144 } 145 146 Register M68kIncomingValueHandler::getStackAddress(uint64_t Size, 147 int64_t Offset, 148 MachinePointerInfo &MPO, 149 ISD::ArgFlagsTy Flags) { 150 auto &MFI = MIRBuilder.getMF().getFrameInfo(); 151 const bool IsImmutable = !Flags.isByVal(); 152 int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); 153 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 154 155 // Build Frame Index 156 llvm::LLT FramePtr = LLT::pointer( 157 0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits()); 158 MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI); 159 StackUsed = std::max(StackUsed, Size + Offset); 160 return AddrReg.getReg(0); 161 } 162 163 void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg, 164 CCValAssign VA) { 165 MIB.addDef(PhysReg, RegState::Implicit); 166 MIRBuilder.buildCopy(ValVReg, PhysReg); 167 } 168 169 bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 170 CallLoweringInfo &Info) const { 171 MachineFunction &MF = MIRBuilder.getMF(); 172 Function &F = MF.getFunction(); 173 MachineRegisterInfo &MRI = MF.getRegInfo(); 174 auto &DL = F.getParent()->getDataLayout(); 175 const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>(); 176 const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>(); 177 const TargetInstrInfo &TII = *STI.getInstrInfo(); 178 const M68kRegisterInfo *TRI = STI.getRegisterInfo(); 179 180 SmallVector<ArgInfo, 8> OutArgs; 181 for (auto &OrigArg : Info.OrigArgs) 182 splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv); 183 184 SmallVector<ArgInfo, 8> InArgs; 185 if (!Info.OrigRet.Ty->isVoidTy()) 186 splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv); 187 188 unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); 189 auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown); 190 191 unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq 192 : Info.Callee.isReg() ? M68k::CALLj 193 : M68k::CALLb; 194 195 auto MIB = MIRBuilder.buildInstrNoInsert(Opc) 196 .add(Info.Callee) 197 .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); 198 199 CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg); 200 OutgoingValueAssigner Assigner(AssignFn); 201 M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB); 202 if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder, 203 Info.CallConv, Info.IsVarArg)) 204 return false; 205 206 if (Info.Callee.isReg()) 207 constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(), 208 *STI.getRegBankInfo(), *MIB, MIB->getDesc(), 209 Info.Callee, 0); 210 211 MIRBuilder.insertInstr(MIB); 212 213 if (!Info.OrigRet.Ty->isVoidTy()) { 214 CCAssignFn *RetAssignFn = 215 TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg); 216 217 OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn); 218 CallReturnHandler Handler(MIRBuilder, MRI, MIB); 219 if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder, 220 Info.CallConv, Info.IsVarArg)) 221 return false; 222 } 223 224 CallSeqStart.addImm(Assigner.StackOffset).addImm(0); 225 226 unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); 227 MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackOffset).addImm(0); 228 229 return true; 230 } 231 232 bool M68kCallLowering::enableBigEndian() const { return true; } 233