1 //===- MipsCallLowering.cpp -------------------------------------*- 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 "MipsCallLowering.h"
16 #include "MipsCCState.h"
17 #include "MipsMachineFunction.h"
18 #include "MipsTargetMachine.h"
19 #include "llvm/CodeGen/Analysis.h"
20 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21
22 using namespace llvm;
23
MipsCallLowering(const MipsTargetLowering & TLI)24 MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
25 : CallLowering(&TLI) {}
26
assign(Register VReg,const CCValAssign & VA,const EVT & VT)27 bool MipsCallLowering::MipsHandler::assign(Register VReg, const CCValAssign &VA,
28 const EVT &VT) {
29 if (VA.isRegLoc()) {
30 assignValueToReg(VReg, VA, VT);
31 } else if (VA.isMemLoc()) {
32 assignValueToAddress(VReg, VA);
33 } else {
34 return false;
35 }
36 return true;
37 }
38
assignVRegs(ArrayRef<Register> VRegs,ArrayRef<CCValAssign> ArgLocs,unsigned ArgLocsStartIndex,const EVT & VT)39 bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<Register> VRegs,
40 ArrayRef<CCValAssign> ArgLocs,
41 unsigned ArgLocsStartIndex,
42 const EVT &VT) {
43 for (unsigned i = 0; i < VRegs.size(); ++i)
44 if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i], VT))
45 return false;
46 return true;
47 }
48
setLeastSignificantFirst(SmallVectorImpl<Register> & VRegs)49 void MipsCallLowering::MipsHandler::setLeastSignificantFirst(
50 SmallVectorImpl<Register> &VRegs) {
51 if (!MIRBuilder.getMF().getDataLayout().isLittleEndian())
52 std::reverse(VRegs.begin(), VRegs.end());
53 }
54
handle(ArrayRef<CCValAssign> ArgLocs,ArrayRef<CallLowering::ArgInfo> Args)55 bool MipsCallLowering::MipsHandler::handle(
56 ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) {
57 SmallVector<Register, 4> VRegs;
58 unsigned SplitLength;
59 const Function &F = MIRBuilder.getMF().getFunction();
60 const DataLayout &DL = F.getParent()->getDataLayout();
61 const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>(
62 MIRBuilder.getMF().getSubtarget().getTargetLowering());
63
64 for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size();
65 ++ArgsIndex, ArgLocsIndex += SplitLength) {
66 EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty);
67 SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(),
68 F.getCallingConv(), VT);
69 assert(Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet");
70
71 if (SplitLength > 1) {
72 VRegs.clear();
73 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(
74 F.getContext(), F.getCallingConv(), VT);
75 for (unsigned i = 0; i < SplitLength; ++i)
76 VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT}));
77
78 if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Regs[0],
79 VT))
80 return false;
81 } else {
82 if (!assign(Args[ArgsIndex].Regs[0], ArgLocs[ArgLocsIndex], VT))
83 return false;
84 }
85 }
86 return true;
87 }
88
89 namespace {
90 class IncomingValueHandler : public MipsCallLowering::MipsHandler {
91 public:
IncomingValueHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI)92 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
93 : MipsHandler(MIRBuilder, MRI) {}
94
95 private:
96 void assignValueToReg(Register ValVReg, const CCValAssign &VA,
97 const EVT &VT) override;
98
99 Register getStackAddress(const CCValAssign &VA,
100 MachineMemOperand *&MMO) override;
101
102 void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override;
103
104 bool handleSplit(SmallVectorImpl<Register> &VRegs,
105 ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex,
106 Register ArgsReg, const EVT &VT) override;
107
markPhysRegUsed(unsigned PhysReg)108 virtual void markPhysRegUsed(unsigned PhysReg) {
109 MIRBuilder.getMRI()->addLiveIn(PhysReg);
110 MIRBuilder.getMBB().addLiveIn(PhysReg);
111 }
112
buildLoad(const DstOp & Res,const CCValAssign & VA)113 MachineInstrBuilder buildLoad(const DstOp &Res, const CCValAssign &VA) {
114 MachineMemOperand *MMO;
115 Register Addr = getStackAddress(VA, MMO);
116 return MIRBuilder.buildLoad(Res, Addr, *MMO);
117 }
118 };
119
120 class CallReturnHandler : public IncomingValueHandler {
121 public:
CallReturnHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI,MachineInstrBuilder & MIB)122 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
123 MachineInstrBuilder &MIB)
124 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
125
126 private:
markPhysRegUsed(unsigned PhysReg)127 void markPhysRegUsed(unsigned PhysReg) override {
128 MIB.addDef(PhysReg, RegState::Implicit);
129 }
130
131 MachineInstrBuilder &MIB;
132 };
133
134 } // end anonymous namespace
135
assignValueToReg(Register ValVReg,const CCValAssign & VA,const EVT & VT)136 void IncomingValueHandler::assignValueToReg(Register ValVReg,
137 const CCValAssign &VA,
138 const EVT &VT) {
139 Register PhysReg = VA.getLocReg();
140 if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) {
141 const MipsSubtarget &STI =
142 static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
143 bool IsEL = STI.isLittle();
144 LLT s32 = LLT::scalar(32);
145 auto Lo = MIRBuilder.buildCopy(s32, Register(PhysReg + (IsEL ? 0 : 1)));
146 auto Hi = MIRBuilder.buildCopy(s32, Register(PhysReg + (IsEL ? 1 : 0)));
147 MIRBuilder.buildMerge(ValVReg, {Lo, Hi});
148 markPhysRegUsed(PhysReg);
149 markPhysRegUsed(PhysReg + 1);
150 } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) {
151 MIRBuilder.buildCopy(ValVReg, PhysReg);
152 markPhysRegUsed(PhysReg);
153 } else {
154 switch (VA.getLocInfo()) {
155 case CCValAssign::LocInfo::SExt:
156 case CCValAssign::LocInfo::ZExt:
157 case CCValAssign::LocInfo::AExt: {
158 auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg);
159 MIRBuilder.buildTrunc(ValVReg, Copy);
160 break;
161 }
162 default:
163 MIRBuilder.buildCopy(ValVReg, PhysReg);
164 break;
165 }
166 markPhysRegUsed(PhysReg);
167 }
168 }
169
getStackAddress(const CCValAssign & VA,MachineMemOperand * & MMO)170 Register IncomingValueHandler::getStackAddress(const CCValAssign &VA,
171 MachineMemOperand *&MMO) {
172 MachineFunction &MF = MIRBuilder.getMF();
173 unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8;
174 unsigned Offset = VA.getLocMemOffset();
175 MachineFrameInfo &MFI = MF.getFrameInfo();
176
177 int FI = MFI.CreateFixedObject(Size, Offset, true);
178 MachinePointerInfo MPO =
179 MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
180
181 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
182 Align Alignment = commonAlignment(TFL->getStackAlign(), Offset);
183 MMO =
184 MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Alignment);
185
186 return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0);
187 }
188
assignValueToAddress(Register ValVReg,const CCValAssign & VA)189 void IncomingValueHandler::assignValueToAddress(Register ValVReg,
190 const CCValAssign &VA) {
191 if (VA.getLocInfo() == CCValAssign::SExt ||
192 VA.getLocInfo() == CCValAssign::ZExt ||
193 VA.getLocInfo() == CCValAssign::AExt) {
194 auto Load = buildLoad(LLT::scalar(32), VA);
195 MIRBuilder.buildTrunc(ValVReg, Load);
196 } else
197 buildLoad(ValVReg, VA);
198 }
199
handleSplit(SmallVectorImpl<Register> & VRegs,ArrayRef<CCValAssign> ArgLocs,unsigned ArgLocsStartIndex,Register ArgsReg,const EVT & VT)200 bool IncomingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs,
201 ArrayRef<CCValAssign> ArgLocs,
202 unsigned ArgLocsStartIndex,
203 Register ArgsReg, const EVT &VT) {
204 if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT))
205 return false;
206 setLeastSignificantFirst(VRegs);
207 MIRBuilder.buildMerge(ArgsReg, VRegs);
208 return true;
209 }
210
211 namespace {
212 class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
213 public:
OutgoingValueHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI,MachineInstrBuilder & MIB)214 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
215 MachineInstrBuilder &MIB)
216 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
217
218 private:
219 void assignValueToReg(Register ValVReg, const CCValAssign &VA,
220 const EVT &VT) override;
221
222 Register getStackAddress(const CCValAssign &VA,
223 MachineMemOperand *&MMO) override;
224
225 void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override;
226
227 bool handleSplit(SmallVectorImpl<Register> &VRegs,
228 ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex,
229 Register ArgsReg, const EVT &VT) override;
230
231 Register extendRegister(Register ValReg, const CCValAssign &VA);
232
233 MachineInstrBuilder &MIB;
234 };
235 } // end anonymous namespace
236
assignValueToReg(Register ValVReg,const CCValAssign & VA,const EVT & VT)237 void OutgoingValueHandler::assignValueToReg(Register ValVReg,
238 const CCValAssign &VA,
239 const EVT &VT) {
240 Register PhysReg = VA.getLocReg();
241 if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) {
242 const MipsSubtarget &STI =
243 static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
244 bool IsEL = STI.isLittle();
245 auto Unmerge = MIRBuilder.buildUnmerge(LLT::scalar(32), ValVReg);
246 MIRBuilder.buildCopy(Register(PhysReg + (IsEL ? 0 : 1)), Unmerge.getReg(0));
247 MIRBuilder.buildCopy(Register(PhysReg + (IsEL ? 1 : 0)), Unmerge.getReg(1));
248 } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) {
249 MIRBuilder.buildCopy(PhysReg, ValVReg);
250 } else {
251 Register ExtReg = extendRegister(ValVReg, VA);
252 MIRBuilder.buildCopy(PhysReg, ExtReg);
253 MIB.addUse(PhysReg, RegState::Implicit);
254 }
255 }
256
getStackAddress(const CCValAssign & VA,MachineMemOperand * & MMO)257 Register OutgoingValueHandler::getStackAddress(const CCValAssign &VA,
258 MachineMemOperand *&MMO) {
259 MachineFunction &MF = MIRBuilder.getMF();
260 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
261
262 LLT p0 = LLT::pointer(0, 32);
263 LLT s32 = LLT::scalar(32);
264 auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP));
265
266 unsigned Offset = VA.getLocMemOffset();
267 auto OffsetReg = MIRBuilder.buildConstant(s32, Offset);
268
269 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
270
271 MachinePointerInfo MPO =
272 MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
273 unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8;
274 Align Alignment = commonAlignment(TFL->getStackAlign(), Offset);
275 MMO =
276 MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Alignment);
277
278 return AddrReg.getReg(0);
279 }
280
assignValueToAddress(Register ValVReg,const CCValAssign & VA)281 void OutgoingValueHandler::assignValueToAddress(Register ValVReg,
282 const CCValAssign &VA) {
283 MachineMemOperand *MMO;
284 Register Addr = getStackAddress(VA, MMO);
285 Register ExtReg = extendRegister(ValVReg, VA);
286 MIRBuilder.buildStore(ExtReg, Addr, *MMO);
287 }
288
extendRegister(Register ValReg,const CCValAssign & VA)289 Register OutgoingValueHandler::extendRegister(Register ValReg,
290 const CCValAssign &VA) {
291 LLT LocTy{VA.getLocVT()};
292 switch (VA.getLocInfo()) {
293 case CCValAssign::SExt: {
294 return MIRBuilder.buildSExt(LocTy, ValReg).getReg(0);
295 }
296 case CCValAssign::ZExt: {
297 return MIRBuilder.buildZExt(LocTy, ValReg).getReg(0);
298 }
299 case CCValAssign::AExt: {
300 return MIRBuilder.buildAnyExt(LocTy, ValReg).getReg(0);
301 }
302 // TODO : handle upper extends
303 case CCValAssign::Full:
304 return ValReg;
305 default:
306 break;
307 }
308 llvm_unreachable("unable to extend register");
309 }
310
handleSplit(SmallVectorImpl<Register> & VRegs,ArrayRef<CCValAssign> ArgLocs,unsigned ArgLocsStartIndex,Register ArgsReg,const EVT & VT)311 bool OutgoingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs,
312 ArrayRef<CCValAssign> ArgLocs,
313 unsigned ArgLocsStartIndex,
314 Register ArgsReg, const EVT &VT) {
315 MIRBuilder.buildUnmerge(VRegs, ArgsReg);
316 setLeastSignificantFirst(VRegs);
317 if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT))
318 return false;
319
320 return true;
321 }
322
isSupportedArgumentType(Type * T)323 static bool isSupportedArgumentType(Type *T) {
324 if (T->isIntegerTy())
325 return true;
326 if (T->isPointerTy())
327 return true;
328 if (T->isFloatingPointTy())
329 return true;
330 return false;
331 }
332
isSupportedReturnType(Type * T)333 static bool isSupportedReturnType(Type *T) {
334 if (T->isIntegerTy())
335 return true;
336 if (T->isPointerTy())
337 return true;
338 if (T->isFloatingPointTy())
339 return true;
340 if (T->isAggregateType())
341 return true;
342 return false;
343 }
344
determineLocInfo(const MVT RegisterVT,const EVT VT,const ISD::ArgFlagsTy & Flags)345 static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT,
346 const ISD::ArgFlagsTy &Flags) {
347 // > does not mean loss of information as type RegisterVT can't hold type VT,
348 // it means that type VT is split into multiple registers of type RegisterVT
349 if (VT.getSizeInBits() >= RegisterVT.getSizeInBits())
350 return CCValAssign::LocInfo::Full;
351 if (Flags.isSExt())
352 return CCValAssign::LocInfo::SExt;
353 if (Flags.isZExt())
354 return CCValAssign::LocInfo::ZExt;
355 return CCValAssign::LocInfo::AExt;
356 }
357
358 template <typename T>
setLocInfo(SmallVectorImpl<CCValAssign> & ArgLocs,const SmallVectorImpl<T> & Arguments)359 static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs,
360 const SmallVectorImpl<T> &Arguments) {
361 for (unsigned i = 0; i < ArgLocs.size(); ++i) {
362 const CCValAssign &VA = ArgLocs[i];
363 CCValAssign::LocInfo LocInfo = determineLocInfo(
364 Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags);
365 if (VA.isMemLoc())
366 ArgLocs[i] =
367 CCValAssign::getMem(VA.getValNo(), VA.getValVT(),
368 VA.getLocMemOffset(), VA.getLocVT(), LocInfo);
369 else
370 ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
371 VA.getLocReg(), VA.getLocVT(), LocInfo);
372 }
373 }
374
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs) const375 bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
376 const Value *Val,
377 ArrayRef<Register> VRegs) const {
378
379 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
380
381 if (Val != nullptr && !isSupportedReturnType(Val->getType()))
382 return false;
383
384 if (!VRegs.empty()) {
385 MachineFunction &MF = MIRBuilder.getMF();
386 const Function &F = MF.getFunction();
387 const DataLayout &DL = MF.getDataLayout();
388 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
389
390 SmallVector<ArgInfo, 8> RetInfos;
391 SmallVector<unsigned, 8> OrigArgIndices;
392
393 ArgInfo ArgRetInfo(VRegs, Val->getType());
394 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
395 splitToValueTypes(DL, ArgRetInfo, 0, RetInfos, OrigArgIndices);
396
397 SmallVector<ISD::OutputArg, 8> Outs;
398 subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs);
399
400 SmallVector<CCValAssign, 16> ArgLocs;
401 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
402 F.getContext());
403 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn());
404 setLocInfo(ArgLocs, Outs);
405
406 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
407 if (!RetHandler.handle(ArgLocs, RetInfos)) {
408 return false;
409 }
410 }
411 MIRBuilder.insertInstr(Ret);
412 return true;
413 }
414
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<ArrayRef<Register>> VRegs) const415 bool MipsCallLowering::lowerFormalArguments(
416 MachineIRBuilder &MIRBuilder, const Function &F,
417 ArrayRef<ArrayRef<Register>> VRegs) const {
418
419 // Quick exit if there aren't any args.
420 if (F.arg_empty())
421 return true;
422
423 for (auto &Arg : F.args()) {
424 if (!isSupportedArgumentType(Arg.getType()))
425 return false;
426 }
427
428 MachineFunction &MF = MIRBuilder.getMF();
429 const DataLayout &DL = MF.getDataLayout();
430 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
431
432 SmallVector<ArgInfo, 8> ArgInfos;
433 SmallVector<unsigned, 8> OrigArgIndices;
434 unsigned i = 0;
435 for (auto &Arg : F.args()) {
436 ArgInfo AInfo(VRegs[i], Arg.getType());
437 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
438 ArgInfos.push_back(AInfo);
439 OrigArgIndices.push_back(i);
440 ++i;
441 }
442
443 SmallVector<ISD::InputArg, 8> Ins;
444 subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins);
445
446 SmallVector<CCValAssign, 16> ArgLocs;
447 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
448 F.getContext());
449
450 const MipsTargetMachine &TM =
451 static_cast<const MipsTargetMachine &>(MF.getTarget());
452 const MipsABIInfo &ABI = TM.getABI();
453 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),
454 Align(1));
455 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
456 setLocInfo(ArgLocs, Ins);
457
458 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
459 if (!Handler.handle(ArgLocs, ArgInfos))
460 return false;
461
462 if (F.isVarArg()) {
463 ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
464 unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
465
466 int VaArgOffset;
467 unsigned RegSize = 4;
468 if (ArgRegs.size() == Idx)
469 VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize);
470 else {
471 VaArgOffset =
472 (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -
473 (int)(RegSize * (ArgRegs.size() - Idx));
474 }
475
476 MachineFrameInfo &MFI = MF.getFrameInfo();
477 int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
478 MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
479
480 for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
481 MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);
482
483 MachineInstrBuilder Copy =
484 MIRBuilder.buildCopy(LLT::scalar(RegSize * 8), Register(ArgRegs[I]));
485 FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
486 MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
487 MachineInstrBuilder FrameIndex =
488 MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI);
489 MachineMemOperand *MMO = MF.getMachineMemOperand(
490 MPO, MachineMemOperand::MOStore, RegSize, Align(RegSize));
491 MIRBuilder.buildStore(Copy, FrameIndex, *MMO);
492 }
493 }
494
495 return true;
496 }
497
lowerCall(MachineIRBuilder & MIRBuilder,CallLoweringInfo & Info) const498 bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
499 CallLoweringInfo &Info) const {
500
501 if (Info.CallConv != CallingConv::C)
502 return false;
503
504 for (auto &Arg : Info.OrigArgs) {
505 if (!isSupportedArgumentType(Arg.Ty))
506 return false;
507 if (Arg.Flags[0].isByVal())
508 return false;
509 if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())
510 return false;
511 }
512
513 if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty))
514 return false;
515
516 MachineFunction &MF = MIRBuilder.getMF();
517 const Function &F = MF.getFunction();
518 const DataLayout &DL = MF.getDataLayout();
519 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
520 const MipsTargetMachine &TM =
521 static_cast<const MipsTargetMachine &>(MF.getTarget());
522 const MipsABIInfo &ABI = TM.getABI();
523
524 MachineInstrBuilder CallSeqStart =
525 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
526
527 const bool IsCalleeGlobalPIC =
528 Info.Callee.isGlobal() && TM.isPositionIndependent();
529
530 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
531 Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
532 MIB.addDef(Mips::SP, RegState::Implicit);
533 if (IsCalleeGlobalPIC) {
534 Register CalleeReg =
535 MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32));
536 MachineInstr *CalleeGlobalValue =
537 MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal());
538 if (!Info.Callee.getGlobal()->hasLocalLinkage())
539 CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL);
540 MIB.addUse(CalleeReg);
541 } else
542 MIB.add(Info.Callee);
543 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
544 MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
545
546 TargetLowering::ArgListTy FuncOrigArgs;
547 FuncOrigArgs.reserve(Info.OrigArgs.size());
548
549 SmallVector<ArgInfo, 8> ArgInfos;
550 SmallVector<unsigned, 8> OrigArgIndices;
551 unsigned i = 0;
552 for (auto &Arg : Info.OrigArgs) {
553
554 TargetLowering::ArgListEntry Entry;
555 Entry.Ty = Arg.Ty;
556 FuncOrigArgs.push_back(Entry);
557
558 ArgInfos.push_back(Arg);
559 OrigArgIndices.push_back(i);
560 ++i;
561 }
562
563 SmallVector<ISD::OutputArg, 8> Outs;
564 subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs);
565
566 SmallVector<CCValAssign, 8> ArgLocs;
567 bool IsCalleeVarArg = false;
568 if (Info.Callee.isGlobal()) {
569 const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
570 IsCalleeVarArg = CF->isVarArg();
571 }
572 MipsCCState CCInfo(F.getCallingConv(), IsCalleeVarArg, MF, ArgLocs,
573 F.getContext());
574
575 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv),
576 Align(1));
577 const char *Call =
578 Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr;
579 CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call);
580 setLocInfo(ArgLocs, Outs);
581
582 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
583 if (!RetHandler.handle(ArgLocs, ArgInfos)) {
584 return false;
585 }
586
587 unsigned NextStackOffset = CCInfo.getNextStackOffset();
588 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
589 unsigned StackAlignment = TFL->getStackAlignment();
590 NextStackOffset = alignTo(NextStackOffset, StackAlignment);
591 CallSeqStart.addImm(NextStackOffset).addImm(0);
592
593 if (IsCalleeGlobalPIC) {
594 MIRBuilder.buildCopy(
595 Register(Mips::GP),
596 MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));
597 MIB.addDef(Mips::GP, RegState::Implicit);
598 }
599 MIRBuilder.insertInstr(MIB);
600 if (MIB->getOpcode() == Mips::JALRPseudo) {
601 const MipsSubtarget &STI =
602 static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
603 MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
604 *STI.getRegBankInfo());
605 }
606
607 if (!Info.OrigRet.Ty->isVoidTy()) {
608 ArgInfos.clear();
609 SmallVector<unsigned, 8> OrigRetIndices;
610
611 splitToValueTypes(DL, Info.OrigRet, 0, ArgInfos, OrigRetIndices);
612
613 SmallVector<ISD::InputArg, 8> Ins;
614 subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins);
615
616 SmallVector<CCValAssign, 8> ArgLocs;
617 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
618 F.getContext());
619
620 CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), Info.OrigRet.Ty,
621 Call);
622 setLocInfo(ArgLocs, Ins);
623
624 CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB);
625 if (!Handler.handle(ArgLocs, ArgInfos))
626 return false;
627 }
628
629 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0);
630
631 return true;
632 }
633
634 template <typename T>
subTargetRegTypeForCallingConv(const Function & F,ArrayRef<ArgInfo> Args,ArrayRef<unsigned> OrigArgIndices,SmallVectorImpl<T> & ISDArgs) const635 void MipsCallLowering::subTargetRegTypeForCallingConv(
636 const Function &F, ArrayRef<ArgInfo> Args,
637 ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const {
638 const DataLayout &DL = F.getParent()->getDataLayout();
639 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
640
641 unsigned ArgNo = 0;
642 for (auto &Arg : Args) {
643
644 EVT VT = TLI.getValueType(DL, Arg.Ty);
645 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(),
646 F.getCallingConv(), VT);
647 unsigned NumRegs = TLI.getNumRegistersForCallingConv(
648 F.getContext(), F.getCallingConv(), VT);
649
650 for (unsigned i = 0; i < NumRegs; ++i) {
651 ISD::ArgFlagsTy Flags = Arg.Flags[0];
652
653 if (i == 0)
654 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
655 else
656 Flags.setOrigAlign(Align(1));
657
658 ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo],
659 0);
660 }
661 ++ArgNo;
662 }
663 }
664
splitToValueTypes(const DataLayout & DL,const ArgInfo & OrigArg,unsigned OriginalIndex,SmallVectorImpl<ArgInfo> & SplitArgs,SmallVectorImpl<unsigned> & SplitArgsOrigIndices) const665 void MipsCallLowering::splitToValueTypes(
666 const DataLayout &DL, const ArgInfo &OrigArg, unsigned OriginalIndex,
667 SmallVectorImpl<ArgInfo> &SplitArgs,
668 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
669
670 SmallVector<EVT, 4> SplitEVTs;
671 SmallVector<Register, 4> SplitVRegs;
672 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
673 LLVMContext &Ctx = OrigArg.Ty->getContext();
674
675 ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitEVTs);
676
677 for (unsigned i = 0; i < SplitEVTs.size(); ++i) {
678 ArgInfo Info = ArgInfo{OrigArg.Regs[i], SplitEVTs[i].getTypeForEVT(Ctx)};
679 Info.Flags = OrigArg.Flags;
680 SplitArgs.push_back(Info);
681 SplitArgsOrigIndices.push_back(OriginalIndex);
682 }
683 }
684