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