blob: fd0f7921ba3a19cb152bceaccb484a90a11f84b5 [file] [log] [blame]
Petar Jovanovicfac93e22018-02-23 11:06:40 +00001//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Petar Jovanovicfac93e22018-02-23 11:06:40 +00006//
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 "MipsCallLowering.h"
Petar Jovanovic366857a2018-04-11 15:12:32 +000016#include "MipsCCState.h"
Petar Jovanovic326ec322018-06-06 07:24:52 +000017#include "MipsTargetMachine.h"
Alexander Ivchenko49168f62018-08-02 08:33:31 +000018#include "llvm/CodeGen/Analysis.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 Jovanovic65d463b2018-08-23 20:41:09 +000026bool MipsCallLowering::MipsHandler::assign(unsigned VReg,
27 const CCValAssign &VA) {
Petar Jovanovic366857a2018-04-11 15:12:32 +000028 if (VA.isRegLoc()) {
Petar Jovanovic65d463b2018-08-23 20:41:09 +000029 assignValueToReg(VReg, VA);
Petar Jovanovic226e6112018-07-03 09:31:48 +000030 } else if (VA.isMemLoc()) {
Petar Jovanovic65d463b2018-08-23 20:41:09 +000031 assignValueToAddress(VReg, VA);
Petar Jovanovic366857a2018-04-11 15:12:32 +000032 } else {
33 return false;
34 }
35 return true;
36}
37
Petar Jovanovicff1bc622018-09-28 13:28:47 +000038bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<unsigned> VRegs,
39 ArrayRef<CCValAssign> ArgLocs,
40 unsigned ArgLocsStartIndex) {
41 for (unsigned i = 0; i < VRegs.size(); ++i)
42 if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i]))
43 return false;
44 return true;
45}
46
Petar Avramovic2624c8d2018-11-07 11:45:43 +000047void MipsCallLowering::MipsHandler::setLeastSignificantFirst(
Petar Jovanovicff1bc622018-09-28 13:28:47 +000048 SmallVectorImpl<unsigned> &VRegs) {
Petar Avramovic2624c8d2018-11-07 11:45:43 +000049 if (!MIRBuilder.getMF().getDataLayout().isLittleEndian())
Petar Jovanovicff1bc622018-09-28 13:28:47 +000050 std::reverse(VRegs.begin(), VRegs.end());
51}
52
53bool MipsCallLowering::MipsHandler::handle(
54 ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) {
55 SmallVector<unsigned, 4> VRegs;
56 unsigned SplitLength;
57 const Function &F = MIRBuilder.getMF().getFunction();
58 const DataLayout &DL = F.getParent()->getDataLayout();
59 const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>(
60 MIRBuilder.getMF().getSubtarget().getTargetLowering());
61
62 for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size();
63 ++ArgsIndex, ArgLocsIndex += SplitLength) {
64 EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty);
65 SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(),
66 F.getCallingConv(), VT);
67 if (SplitLength > 1) {
68 VRegs.clear();
69 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(
70 F.getContext(), F.getCallingConv(), VT);
71 for (unsigned i = 0; i < SplitLength; ++i)
72 VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT}));
73
74 if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Reg))
75 return false;
76 } else {
77 if (!assign(Args[ArgsIndex].Reg, ArgLocs[ArgLocsIndex]))
78 return false;
79 }
80 }
81 return true;
82}
83
Petar Jovanovic366857a2018-04-11 15:12:32 +000084namespace {
85class IncomingValueHandler : public MipsCallLowering::MipsHandler {
86public:
87 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
88 : MipsHandler(MIRBuilder, MRI) {}
89
Petar Jovanovic366857a2018-04-11 15:12:32 +000090private:
Petar Jovanovic65d463b2018-08-23 20:41:09 +000091 void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override;
Petar Jovanovic226e6112018-07-03 09:31:48 +000092
Petar Jovanovic65d463b2018-08-23 20:41:09 +000093 unsigned getStackAddress(const CCValAssign &VA,
94 MachineMemOperand *&MMO) override;
Petar Jovanovic226e6112018-07-03 09:31:48 +000095
Petar Jovanovic65d463b2018-08-23 20:41:09 +000096 void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override;
Petar Jovanovic366857a2018-04-11 15:12:32 +000097
Petar Jovanovicff1bc622018-09-28 13:28:47 +000098 bool handleSplit(SmallVectorImpl<unsigned> &VRegs,
99 ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex,
100 unsigned ArgsReg) override;
101
Petar Jovanovic326ec322018-06-06 07:24:52 +0000102 virtual void markPhysRegUsed(unsigned PhysReg) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000103 MIRBuilder.getMBB().addLiveIn(PhysReg);
104 }
Petar Jovanovic226e6112018-07-03 09:31:48 +0000105
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000106 void buildLoad(unsigned Val, const CCValAssign &VA) {
107 MachineMemOperand *MMO;
108 unsigned Addr = getStackAddress(VA, MMO);
Petar Jovanovic226e6112018-07-03 09:31:48 +0000109 MIRBuilder.buildLoad(Val, Addr, *MMO);
110 }
Petar Jovanovic366857a2018-04-11 15:12:32 +0000111};
Petar Jovanovic326ec322018-06-06 07:24:52 +0000112
113class CallReturnHandler : public IncomingValueHandler {
114public:
115 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
116 MachineInstrBuilder &MIB)
117 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
118
119private:
Petar Jovanovic226e6112018-07-03 09:31:48 +0000120 void markPhysRegUsed(unsigned PhysReg) override {
Petar Jovanovic326ec322018-06-06 07:24:52 +0000121 MIB.addDef(PhysReg, RegState::Implicit);
122 }
123
124 MachineInstrBuilder &MIB;
125};
126
Petar Jovanovic366857a2018-04-11 15:12:32 +0000127} // end anonymous namespace
128
129void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000130 const CCValAssign &VA) {
131 unsigned PhysReg = VA.getLocReg();
132 switch (VA.getLocInfo()) {
133 case CCValAssign::LocInfo::SExt:
134 case CCValAssign::LocInfo::ZExt:
135 case CCValAssign::LocInfo::AExt: {
136 auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg);
137 MIRBuilder.buildTrunc(ValVReg, Copy);
138 break;
139 }
140 default:
141 MIRBuilder.buildCopy(ValVReg, PhysReg);
142 break;
143 }
Petar Jovanovic366857a2018-04-11 15:12:32 +0000144 markPhysRegUsed(PhysReg);
145}
146
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000147unsigned IncomingValueHandler::getStackAddress(const CCValAssign &VA,
148 MachineMemOperand *&MMO) {
Matt Arsenault2a645982019-01-31 01:38:47 +0000149 MachineFunction &MF = MIRBuilder.getMF();
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000150 unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8;
151 unsigned Offset = VA.getLocMemOffset();
Matt Arsenault2a645982019-01-31 01:38:47 +0000152 MachineFrameInfo &MFI = MF.getFrameInfo();
Petar Jovanovic226e6112018-07-03 09:31:48 +0000153
154 int FI = MFI.CreateFixedObject(Size, Offset, true);
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000155 MachinePointerInfo MPO =
156 MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
Matt Arsenault2a645982019-01-31 01:38:47 +0000157
158 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
159 unsigned Align = MinAlign(TFL->getStackAlignment(), Offset);
160 MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Align);
Petar Jovanovic226e6112018-07-03 09:31:48 +0000161
162 unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
163 MIRBuilder.buildFrameIndex(AddrReg, FI);
164
165 return AddrReg;
166}
167
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000168void IncomingValueHandler::assignValueToAddress(unsigned ValVReg,
169 const CCValAssign &VA) {
170 if (VA.getLocInfo() == CCValAssign::SExt ||
171 VA.getLocInfo() == CCValAssign::ZExt ||
172 VA.getLocInfo() == CCValAssign::AExt) {
173 unsigned LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
174 buildLoad(LoadReg, VA);
175 MIRBuilder.buildTrunc(ValVReg, LoadReg);
176 } else
177 buildLoad(ValVReg, VA);
Petar Jovanovic226e6112018-07-03 09:31:48 +0000178}
179
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000180bool IncomingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs,
181 ArrayRef<CCValAssign> ArgLocs,
182 unsigned ArgLocsStartIndex,
183 unsigned ArgsReg) {
184 if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex))
185 return false;
Petar Avramovic2624c8d2018-11-07 11:45:43 +0000186 setLeastSignificantFirst(VRegs);
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000187 MIRBuilder.buildMerge(ArgsReg, VRegs);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000188 return true;
189}
190
191namespace {
192class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
193public:
194 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
195 MachineInstrBuilder &MIB)
196 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
197
Petar Jovanovic366857a2018-04-11 15:12:32 +0000198private:
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000199 void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override;
Petar Jovanovic226e6112018-07-03 09:31:48 +0000200
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000201 unsigned getStackAddress(const CCValAssign &VA,
202 MachineMemOperand *&MMO) override;
Petar Jovanovic226e6112018-07-03 09:31:48 +0000203
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000204 void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override;
205
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000206 bool handleSplit(SmallVectorImpl<unsigned> &VRegs,
207 ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex,
208 unsigned ArgsReg) override;
209
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000210 unsigned extendRegister(unsigned ValReg, const CCValAssign &VA);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000211
212 MachineInstrBuilder &MIB;
213};
214} // end anonymous namespace
215
216void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000217 const CCValAssign &VA) {
218 unsigned PhysReg = VA.getLocReg();
219 unsigned ExtReg = extendRegister(ValVReg, VA);
220 MIRBuilder.buildCopy(PhysReg, ExtReg);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000221 MIB.addUse(PhysReg, RegState::Implicit);
222}
223
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000224unsigned OutgoingValueHandler::getStackAddress(const CCValAssign &VA,
225 MachineMemOperand *&MMO) {
Matt Arsenault2a645982019-01-31 01:38:47 +0000226 MachineFunction &MF = MIRBuilder.getMF();
227 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
228
Petar Jovanovic226e6112018-07-03 09:31:48 +0000229 LLT p0 = LLT::pointer(0, 32);
230 LLT s32 = LLT::scalar(32);
231 unsigned SPReg = MRI.createGenericVirtualRegister(p0);
232 MIRBuilder.buildCopy(SPReg, Mips::SP);
233
234 unsigned OffsetReg = MRI.createGenericVirtualRegister(s32);
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000235 unsigned Offset = VA.getLocMemOffset();
Petar Jovanovic226e6112018-07-03 09:31:48 +0000236 MIRBuilder.buildConstant(OffsetReg, Offset);
237
238 unsigned AddrReg = MRI.createGenericVirtualRegister(p0);
239 MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg);
240
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000241 MachinePointerInfo MPO =
242 MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
243 unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8;
Matt Arsenault2a645982019-01-31 01:38:47 +0000244 unsigned Align = MinAlign(TFL->getStackAlignment(), Offset);
245 MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Align);
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000246
Petar Jovanovic226e6112018-07-03 09:31:48 +0000247 return AddrReg;
248}
249
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000250void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg,
251 const CCValAssign &VA) {
252 MachineMemOperand *MMO;
253 unsigned Addr = getStackAddress(VA, MMO);
254 unsigned ExtReg = extendRegister(ValVReg, VA);
255 MIRBuilder.buildStore(ExtReg, Addr, *MMO);
256}
257
258unsigned OutgoingValueHandler::extendRegister(unsigned ValReg,
259 const CCValAssign &VA) {
260 LLT LocTy{VA.getLocVT()};
261 switch (VA.getLocInfo()) {
262 case CCValAssign::SExt: {
263 unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy);
264 MIRBuilder.buildSExt(ExtReg, ValReg);
265 return ExtReg;
266 }
267 case CCValAssign::ZExt: {
268 unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy);
269 MIRBuilder.buildZExt(ExtReg, ValReg);
270 return ExtReg;
271 }
272 case CCValAssign::AExt: {
273 unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy);
274 MIRBuilder.buildAnyExt(ExtReg, ValReg);
275 return ExtReg;
276 }
277 // TODO : handle upper extends
278 case CCValAssign::Full:
279 return ValReg;
280 default:
281 break;
282 }
283 llvm_unreachable("unable to extend register");
Petar Jovanovic226e6112018-07-03 09:31:48 +0000284}
285
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000286bool OutgoingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs,
287 ArrayRef<CCValAssign> ArgLocs,
288 unsigned ArgLocsStartIndex,
289 unsigned ArgsReg) {
290 MIRBuilder.buildUnmerge(VRegs, ArgsReg);
Petar Avramovic2624c8d2018-11-07 11:45:43 +0000291 setLeastSignificantFirst(VRegs);
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000292 if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex))
293 return false;
294
Petar Jovanovic366857a2018-04-11 15:12:32 +0000295 return true;
296}
297
298static bool isSupportedType(Type *T) {
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000299 if (T->isIntegerTy())
Petar Jovanovic366857a2018-04-11 15:12:32 +0000300 return true;
Petar Jovanovic58c02102018-07-25 12:35:01 +0000301 if (T->isPointerTy())
302 return true;
Petar Jovanovic366857a2018-04-11 15:12:32 +0000303 return false;
304}
305
Benjamin Kramerc55e9972018-10-13 22:18:22 +0000306static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT,
307 const ISD::ArgFlagsTy &Flags) {
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000308 // > does not mean loss of information as type RegisterVT can't hold type VT,
309 // it means that type VT is split into multiple registers of type RegisterVT
310 if (VT.getSizeInBits() >= RegisterVT.getSizeInBits())
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000311 return CCValAssign::LocInfo::Full;
312 if (Flags.isSExt())
313 return CCValAssign::LocInfo::SExt;
314 if (Flags.isZExt())
315 return CCValAssign::LocInfo::ZExt;
316 return CCValAssign::LocInfo::AExt;
317}
318
319template <typename T>
Benjamin Kramerc55e9972018-10-13 22:18:22 +0000320static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs,
321 const SmallVectorImpl<T> &Arguments) {
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000322 for (unsigned i = 0; i < ArgLocs.size(); ++i) {
323 const CCValAssign &VA = ArgLocs[i];
324 CCValAssign::LocInfo LocInfo = determineLocInfo(
325 Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags);
326 if (VA.isMemLoc())
327 ArgLocs[i] =
328 CCValAssign::getMem(VA.getValNo(), VA.getValVT(),
329 VA.getLocMemOffset(), VA.getLocVT(), LocInfo);
330 else
331 ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
332 VA.getLocReg(), VA.getLocVT(), LocInfo);
333 }
334}
335
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000336bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000337 const Value *Val,
338 ArrayRef<unsigned> VRegs) const {
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000339
340 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
341
Alexander Ivchenko49168f62018-08-02 08:33:31 +0000342 if (Val != nullptr && !isSupportedType(Val->getType()))
343 return false;
Petar Jovanovic366857a2018-04-11 15:12:32 +0000344
Alexander Ivchenko49168f62018-08-02 08:33:31 +0000345 if (!VRegs.empty()) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000346 MachineFunction &MF = MIRBuilder.getMF();
347 const Function &F = MF.getFunction();
348 const DataLayout &DL = MF.getDataLayout();
349 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
Alexander Ivchenko49168f62018-08-02 08:33:31 +0000350 LLVMContext &Ctx = Val->getType()->getContext();
351
352 SmallVector<EVT, 4> SplitEVTs;
353 ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
354 assert(VRegs.size() == SplitEVTs.size() &&
355 "For each split Type there should be exactly one VReg.");
Petar Jovanovic366857a2018-04-11 15:12:32 +0000356
357 SmallVector<ArgInfo, 8> RetInfos;
358 SmallVector<unsigned, 8> OrigArgIndices;
359
Alexander Ivchenko49168f62018-08-02 08:33:31 +0000360 for (unsigned i = 0; i < SplitEVTs.size(); ++i) {
361 ArgInfo CurArgInfo = ArgInfo{VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)};
362 setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F);
363 splitToValueTypes(CurArgInfo, 0, RetInfos, OrigArgIndices);
364 }
Petar Jovanovic366857a2018-04-11 15:12:32 +0000365
366 SmallVector<ISD::OutputArg, 8> Outs;
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000367 subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000368
369 SmallVector<CCValAssign, 16> ArgLocs;
370 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
371 F.getContext());
372 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn());
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000373 setLocInfo(ArgLocs, Outs);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000374
375 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
376 if (!RetHandler.handle(ArgLocs, RetInfos)) {
377 return false;
378 }
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000379 }
380 MIRBuilder.insertInstr(Ret);
381 return true;
382}
383
384bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
385 const Function &F,
386 ArrayRef<unsigned> VRegs) const {
387
388 // Quick exit if there aren't any args.
389 if (F.arg_empty())
390 return true;
391
Petar Jovanovic366857a2018-04-11 15:12:32 +0000392 if (F.isVarArg()) {
393 return false;
394 }
395
396 for (auto &Arg : F.args()) {
397 if (!isSupportedType(Arg.getType()))
398 return false;
399 }
400
401 MachineFunction &MF = MIRBuilder.getMF();
402 const DataLayout &DL = MF.getDataLayout();
403 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
404
405 SmallVector<ArgInfo, 8> ArgInfos;
406 SmallVector<unsigned, 8> OrigArgIndices;
407 unsigned i = 0;
408 for (auto &Arg : F.args()) {
409 ArgInfo AInfo(VRegs[i], Arg.getType());
410 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
411 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices);
412 ++i;
413 }
414
415 SmallVector<ISD::InputArg, 8> Ins;
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000416 subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000417
418 SmallVector<CCValAssign, 16> ArgLocs;
419 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
420 F.getContext());
421
Petar Jovanovic226e6112018-07-03 09:31:48 +0000422 const MipsTargetMachine &TM =
423 static_cast<const MipsTargetMachine &>(MF.getTarget());
424 const MipsABIInfo &ABI = TM.getABI();
425 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),
426 1);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000427 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000428 setLocInfo(ArgLocs, Ins);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000429
Petar Jovanovic667e2132018-04-12 17:01:46 +0000430 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
Petar Jovanovic366857a2018-04-11 15:12:32 +0000431 if (!Handler.handle(ArgLocs, ArgInfos))
432 return false;
433
434 return true;
435}
436
Petar Jovanovic326ec322018-06-06 07:24:52 +0000437bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
438 CallingConv::ID CallConv,
439 const MachineOperand &Callee,
440 const ArgInfo &OrigRet,
441 ArrayRef<ArgInfo> OrigArgs) const {
442
443 if (CallConv != CallingConv::C)
444 return false;
445
446 for (auto &Arg : OrigArgs) {
447 if (!isSupportedType(Arg.Ty))
448 return false;
449 if (Arg.Flags.isByVal() || Arg.Flags.isSRet())
450 return false;
451 }
452 if (OrigRet.Reg && !isSupportedType(OrigRet.Ty))
453 return false;
454
455 MachineFunction &MF = MIRBuilder.getMF();
456 const Function &F = MF.getFunction();
457 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
458 const MipsTargetMachine &TM =
459 static_cast<const MipsTargetMachine &>(MF.getTarget());
460 const MipsABIInfo &ABI = TM.getABI();
461
462 MachineInstrBuilder CallSeqStart =
463 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
464
465 // FIXME: Add support for pic calling sequences, long call sequences for O32,
466 // N32 and N64. First handle the case when Callee.isReg().
467 if (Callee.isReg())
468 return false;
469
470 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL);
471 MIB.addDef(Mips::SP, RegState::Implicit);
472 MIB.add(Callee);
473 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
474 MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
475
476 TargetLowering::ArgListTy FuncOrigArgs;
477 FuncOrigArgs.reserve(OrigArgs.size());
478
479 SmallVector<ArgInfo, 8> ArgInfos;
480 SmallVector<unsigned, 8> OrigArgIndices;
481 unsigned i = 0;
482 for (auto &Arg : OrigArgs) {
483
484 TargetLowering::ArgListEntry Entry;
485 Entry.Ty = Arg.Ty;
486 FuncOrigArgs.push_back(Entry);
487
488 splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices);
489 ++i;
490 }
491
492 SmallVector<ISD::OutputArg, 8> Outs;
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000493 subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000494
495 SmallVector<CCValAssign, 8> ArgLocs;
496 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
497 F.getContext());
498
Petar Jovanovic226e6112018-07-03 09:31:48 +0000499 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000500 const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr;
501 CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call);
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000502 setLocInfo(ArgLocs, Outs);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000503
504 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
505 if (!RetHandler.handle(ArgLocs, ArgInfos)) {
506 return false;
507 }
508
Petar Jovanovic226e6112018-07-03 09:31:48 +0000509 unsigned NextStackOffset = CCInfo.getNextStackOffset();
510 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
511 unsigned StackAlignment = TFL->getStackAlignment();
512 NextStackOffset = alignTo(NextStackOffset, StackAlignment);
513 CallSeqStart.addImm(NextStackOffset).addImm(0);
514
Petar Jovanovic326ec322018-06-06 07:24:52 +0000515 MIRBuilder.insertInstr(MIB);
516
517 if (OrigRet.Reg) {
518
519 ArgInfos.clear();
520 SmallVector<unsigned, 8> OrigRetIndices;
521
522 splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices);
523
524 SmallVector<ISD::InputArg, 8> Ins;
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000525 subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000526
527 SmallVector<CCValAssign, 8> ArgLocs;
528 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
529 F.getContext());
530
531 CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call);
Petar Jovanovic65d463b2018-08-23 20:41:09 +0000532 setLocInfo(ArgLocs, Ins);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000533
534 CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB);
535 if (!Handler.handle(ArgLocs, ArgInfos))
536 return false;
537 }
538
Petar Jovanovic226e6112018-07-03 09:31:48 +0000539 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000540
541 return true;
542}
543
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000544template <typename T>
Petar Jovanovic366857a2018-04-11 15:12:32 +0000545void MipsCallLowering::subTargetRegTypeForCallingConv(
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000546 const Function &F, ArrayRef<ArgInfo> Args,
547 ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000548 const DataLayout &DL = F.getParent()->getDataLayout();
549 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
550
551 unsigned ArgNo = 0;
552 for (auto &Arg : Args) {
553
554 EVT VT = TLI.getValueType(DL, Arg.Ty);
Matt Arsenault81920b02018-07-28 13:25:19 +0000555 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(),
556 F.getCallingConv(), VT);
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000557 unsigned NumRegs = TLI.getNumRegistersForCallingConv(
558 F.getContext(), F.getCallingConv(), VT);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000559
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000560 for (unsigned i = 0; i < NumRegs; ++i) {
561 ISD::ArgFlagsTy Flags = Arg.Flags;
Petar Jovanovic366857a2018-04-11 15:12:32 +0000562
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000563 if (i == 0)
564 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
565 else
566 Flags.setOrigAlign(1);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000567
Petar Jovanovicff1bc622018-09-28 13:28:47 +0000568 ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo],
569 0);
570 }
Petar Jovanovic366857a2018-04-11 15:12:32 +0000571 ++ArgNo;
572 }
573}
574
575void MipsCallLowering::splitToValueTypes(
576 const ArgInfo &OrigArg, unsigned OriginalIndex,
577 SmallVectorImpl<ArgInfo> &SplitArgs,
578 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
579
580 // TODO : perform structure and array split. For now we only deal with
581 // types that pass isSupportedType check.
582 SplitArgs.push_back(OrigArg);
583 SplitArgsOrigIndices.push_back(OriginalIndex);
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000584}