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 {
M68kFormalArgHandler__anona60cc7670111::M68kFormalArgHandler31 M68kFormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
32 : M68kIncomingValueHandler(MIRBuilder, MRI) {}
33 };
34
35 struct CallReturnHandler : public M68kIncomingValueHandler {
CallReturnHandler__anona60cc7670111::CallReturnHandler36 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
M68kCallLowering(const M68kTargetLowering & TLI)49 M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
50 : CallLowering(&TLI) {}
51
52 struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
M68kOutgoingArgHandlerM68kOutgoingArgHandler53 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
assignValueToRegM68kOutgoingArgHandler59 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
assignValueToAddressM68kOutgoingArgHandler66 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
getStackAddressM68kOutgoingArgHandler77 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 };
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs,FunctionLoweringInfo & FLI,Register SwiftErrorVReg) const93 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.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
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<ArrayRef<Register>> VRegs,FunctionLoweringInfo & FLI) const122 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.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
assignValueToReg(Register ValVReg,Register PhysReg,const CCValAssign & VA)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
assignValueToAddress(Register ValVReg,Register Addr,LLT MemTy,const MachinePointerInfo & MPO,const CCValAssign & VA)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
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO,ISD::ArgFlagsTy Flags)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
assignValueToReg(Register ValVReg,Register PhysReg,const CCValAssign & VA)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
lowerCall(MachineIRBuilder & MIRBuilder,CallLoweringInfo & Info) const189 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.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
enableBigEndian() const252 bool M68kCallLowering::enableBigEndian() const { return true; }
253