blob: cd751e5825fc8fa5cf310aed94cdeccce27b45a7 [file] [log] [blame]
Petar Jovanovicfac93e22018-02-23 11:06:40 +00001//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
11/// This file implements the lowering of LLVM calls to machine code calls for
12/// GlobalISel.
13//
14//===----------------------------------------------------------------------===//
15
16#include "MipsCallLowering.h"
Petar Jovanovic366857a2018-04-11 15:12:32 +000017#include "MipsCCState.h"
Petar Jovanovic326ec322018-06-06 07:24:52 +000018#include "MipsTargetMachine.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000019#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20
21using namespace llvm;
22
23MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
24 : CallLowering(&TLI) {}
25
Petar Jovanovic366857a2018-04-11 15:12:32 +000026bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA,
27 unsigned vreg) {
28 if (VA.isRegLoc()) {
29 assignValueToReg(vreg, VA.getLocReg());
30 } else {
31 return false;
32 }
33 return true;
34}
35
36namespace {
37class IncomingValueHandler : public MipsCallLowering::MipsHandler {
38public:
39 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
40 : MipsHandler(MIRBuilder, MRI) {}
41
42 bool handle(ArrayRef<CCValAssign> ArgLocs,
43 ArrayRef<CallLowering::ArgInfo> Args);
44
45private:
46 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
47
Petar Jovanovic326ec322018-06-06 07:24:52 +000048 virtual void markPhysRegUsed(unsigned PhysReg) {
Petar Jovanovic366857a2018-04-11 15:12:32 +000049 MIRBuilder.getMBB().addLiveIn(PhysReg);
50 }
51};
Petar Jovanovic326ec322018-06-06 07:24:52 +000052
53class CallReturnHandler : public IncomingValueHandler {
54public:
55 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
56 MachineInstrBuilder &MIB)
57 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
58
59private:
60 virtual void markPhysRegUsed(unsigned PhysReg) override {
61 MIB.addDef(PhysReg, RegState::Implicit);
62 }
63
64 MachineInstrBuilder &MIB;
65};
66
Petar Jovanovic366857a2018-04-11 15:12:32 +000067} // end anonymous namespace
68
69void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
70 unsigned PhysReg) {
71 MIRBuilder.buildCopy(ValVReg, PhysReg);
72 markPhysRegUsed(PhysReg);
73}
74
75bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
76 ArrayRef<CallLowering::ArgInfo> Args) {
77 for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) {
78 if (!assign(ArgLocs[i], Args[i].Reg))
79 return false;
80 }
81 return true;
82}
83
84namespace {
85class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
86public:
87 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
88 MachineInstrBuilder &MIB)
89 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
90
91 bool handle(ArrayRef<CCValAssign> ArgLocs,
92 ArrayRef<CallLowering::ArgInfo> Args);
93
94private:
95 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
96
97 MachineInstrBuilder &MIB;
98};
99} // end anonymous namespace
100
101void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
102 unsigned PhysReg) {
103 MIRBuilder.buildCopy(PhysReg, ValVReg);
104 MIB.addUse(PhysReg, RegState::Implicit);
105}
106
107bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
108 ArrayRef<CallLowering::ArgInfo> Args) {
109 for (unsigned i = 0; i < Args.size(); ++i) {
110 if (!assign(ArgLocs[i], Args[i].Reg))
111 return false;
112 }
113 return true;
114}
115
116static bool isSupportedType(Type *T) {
117 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32)
118 return true;
119 return false;
120}
121
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000122bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
123 const Value *Val, unsigned VReg) const {
124
125 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
126
127 if (Val != nullptr) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000128 if (!isSupportedType(Val->getType()))
129 return false;
130
131 MachineFunction &MF = MIRBuilder.getMF();
132 const Function &F = MF.getFunction();
133 const DataLayout &DL = MF.getDataLayout();
134 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
135
136 SmallVector<ArgInfo, 8> RetInfos;
137 SmallVector<unsigned, 8> OrigArgIndices;
138
139 ArgInfo ArgRetInfo(VReg, Val->getType());
140 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
141 splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices);
142
143 SmallVector<ISD::OutputArg, 8> Outs;
144 subTargetRegTypeForCallingConv(
145 MIRBuilder, RetInfos, OrigArgIndices,
146 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
147 unsigned origIdx, unsigned partOffs) {
148 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
149 });
150
151 SmallVector<CCValAssign, 16> ArgLocs;
152 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
153 F.getContext());
154 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn());
155
156 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
157 if (!RetHandler.handle(ArgLocs, RetInfos)) {
158 return false;
159 }
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000160 }
161 MIRBuilder.insertInstr(Ret);
162 return true;
163}
164
165bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
166 const Function &F,
167 ArrayRef<unsigned> VRegs) const {
168
169 // Quick exit if there aren't any args.
170 if (F.arg_empty())
171 return true;
172
Petar Jovanovic366857a2018-04-11 15:12:32 +0000173 if (F.isVarArg()) {
174 return false;
175 }
176
177 for (auto &Arg : F.args()) {
178 if (!isSupportedType(Arg.getType()))
179 return false;
180 }
181
182 MachineFunction &MF = MIRBuilder.getMF();
183 const DataLayout &DL = MF.getDataLayout();
184 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
185
186 SmallVector<ArgInfo, 8> ArgInfos;
187 SmallVector<unsigned, 8> OrigArgIndices;
188 unsigned i = 0;
189 for (auto &Arg : F.args()) {
190 ArgInfo AInfo(VRegs[i], Arg.getType());
191 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
192 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices);
193 ++i;
194 }
195
196 SmallVector<ISD::InputArg, 8> Ins;
197 subTargetRegTypeForCallingConv(
198 MIRBuilder, ArgInfos, OrigArgIndices,
199 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
200 unsigned partOffs) {
201 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
202 });
203
204 SmallVector<CCValAssign, 16> ArgLocs;
205 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
206 F.getContext());
207
208 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
209
Petar Jovanovic667e2132018-04-12 17:01:46 +0000210 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
Petar Jovanovic366857a2018-04-11 15:12:32 +0000211 if (!Handler.handle(ArgLocs, ArgInfos))
212 return false;
213
214 return true;
215}
216
Petar Jovanovic326ec322018-06-06 07:24:52 +0000217bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
218 CallingConv::ID CallConv,
219 const MachineOperand &Callee,
220 const ArgInfo &OrigRet,
221 ArrayRef<ArgInfo> OrigArgs) const {
222
223 if (CallConv != CallingConv::C)
224 return false;
225
226 for (auto &Arg : OrigArgs) {
227 if (!isSupportedType(Arg.Ty))
228 return false;
229 if (Arg.Flags.isByVal() || Arg.Flags.isSRet())
230 return false;
231 }
232 if (OrigRet.Reg && !isSupportedType(OrigRet.Ty))
233 return false;
234
235 MachineFunction &MF = MIRBuilder.getMF();
236 const Function &F = MF.getFunction();
237 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
238 const MipsTargetMachine &TM =
239 static_cast<const MipsTargetMachine &>(MF.getTarget());
240 const MipsABIInfo &ABI = TM.getABI();
241
242 MachineInstrBuilder CallSeqStart =
243 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
244
245 // FIXME: Add support for pic calling sequences, long call sequences for O32,
246 // N32 and N64. First handle the case when Callee.isReg().
247 if (Callee.isReg())
248 return false;
249
250 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL);
251 MIB.addDef(Mips::SP, RegState::Implicit);
252 MIB.add(Callee);
253 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
254 MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
255
256 TargetLowering::ArgListTy FuncOrigArgs;
257 FuncOrigArgs.reserve(OrigArgs.size());
258
259 SmallVector<ArgInfo, 8> ArgInfos;
260 SmallVector<unsigned, 8> OrigArgIndices;
261 unsigned i = 0;
262 for (auto &Arg : OrigArgs) {
263
264 TargetLowering::ArgListEntry Entry;
265 Entry.Ty = Arg.Ty;
266 FuncOrigArgs.push_back(Entry);
267
268 splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices);
269 ++i;
270 }
271
272 SmallVector<ISD::OutputArg, 8> Outs;
273 subTargetRegTypeForCallingConv(
274 MIRBuilder, ArgInfos, OrigArgIndices,
275 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
276 unsigned partOffs) {
277 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
278 });
279
280 SmallVector<CCValAssign, 8> ArgLocs;
281 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
282 F.getContext());
283
284 const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr;
285 CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call);
286
287 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
288 if (!RetHandler.handle(ArgLocs, ArgInfos)) {
289 return false;
290 }
291
292 // TODO: Calculate stack offset.
293 CallSeqStart.addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)).addImm(0);
294 MIRBuilder.insertInstr(MIB);
295
296 if (OrigRet.Reg) {
297
298 ArgInfos.clear();
299 SmallVector<unsigned, 8> OrigRetIndices;
300
301 splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices);
302
303 SmallVector<ISD::InputArg, 8> Ins;
304 subTargetRegTypeForCallingConv(
305 MIRBuilder, ArgInfos, OrigRetIndices,
306 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
307 unsigned origIdx, unsigned partOffs) {
308 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
309 });
310
311 SmallVector<CCValAssign, 8> ArgLocs;
312 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
313 F.getContext());
314
315 CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call);
316
317 CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB);
318 if (!Handler.handle(ArgLocs, ArgInfos))
319 return false;
320 }
321
322 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP)
323 .addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv))
324 .addImm(0);
325
326 return true;
327}
328
Petar Jovanovic366857a2018-04-11 15:12:32 +0000329void MipsCallLowering::subTargetRegTypeForCallingConv(
330 MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
331 ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const {
332 MachineFunction &MF = MIRBuilder.getMF();
333 const Function &F = MF.getFunction();
334 const DataLayout &DL = F.getParent()->getDataLayout();
335 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
336
337 unsigned ArgNo = 0;
338 for (auto &Arg : Args) {
339
340 EVT VT = TLI.getValueType(DL, Arg.Ty);
341 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), VT);
342
343 ISD::ArgFlagsTy Flags = Arg.Flags;
344 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
345
346 PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0);
347
348 ++ArgNo;
349 }
350}
351
352void MipsCallLowering::splitToValueTypes(
353 const ArgInfo &OrigArg, unsigned OriginalIndex,
354 SmallVectorImpl<ArgInfo> &SplitArgs,
355 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
356
357 // TODO : perform structure and array split. For now we only deal with
358 // types that pass isSupportedType check.
359 SplitArgs.push_back(OrigArg);
360 SplitArgsOrigIndices.push_back(OriginalIndex);
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000361}