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#include "llvm/CodeGen/MachineFrameInfo.h"
22
23using namespace llvm;
24
25MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
26 : CallLowering(&TLI) {}
27
28namespace {
29class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler {
30 const MipsSubtarget &STI;
31
32public:
33 MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder,
34 MachineRegisterInfo &MRI)
35 : IncomingValueHandler(MIRBuilder, MRI),
36 STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()) {}
37
38private:
39 void assignValueToReg(Register ValVReg, Register PhysReg,
40 const CCValAssign &VA,
41 ISD::ArgFlagsTy Flags = {}) override;
42
43 Register getStackAddress(uint64_t Size, int64_t Offset,
44 MachinePointerInfo &MPO,
45 ISD::ArgFlagsTy Flags) override;
46 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
47 const MachinePointerInfo &MPO,
48 const CCValAssign &VA) override;
49
50 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
51 ArrayRef<CCValAssign> VAs,
52 std::function<void()> *Thunk = nullptr) override;
53
54 virtual void markPhysRegUsed(unsigned PhysReg) {
55 MIRBuilder.getMRI()->addLiveIn(Reg: PhysReg);
56 MIRBuilder.getMBB().addLiveIn(PhysReg);
57 }
58};
59
60class CallReturnHandler : public MipsIncomingValueHandler {
61public:
62 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
63 MachineInstrBuilder &MIB)
64 : MipsIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
65
66private:
67 void markPhysRegUsed(unsigned PhysReg) override {
68 MIB.addDef(RegNo: PhysReg, Flags: RegState::Implicit);
69 }
70
71 MachineInstrBuilder &MIB;
72};
73
74} // end anonymous namespace
75
76void MipsIncomingValueHandler::assignValueToReg(Register ValVReg,
77 Register PhysReg,
78 const CCValAssign &VA,
79 ISD::ArgFlagsTy Flags) {
80 markPhysRegUsed(PhysReg);
81 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
82}
83
84Register MipsIncomingValueHandler::getStackAddress(uint64_t Size,
85 int64_t Offset,
86 MachinePointerInfo &MPO,
87 ISD::ArgFlagsTy Flags) {
88
89 MachineFunction &MF = MIRBuilder.getMF();
90 MachineFrameInfo &MFI = MF.getFrameInfo();
91
92 // FIXME: This should only be immutable for non-byval memory arguments.
93 int FI = MFI.CreateFixedObject(Size, SPOffset: Offset, IsImmutable: true);
94 MPO = MachinePointerInfo::getFixedStack(MF&: MIRBuilder.getMF(), FI);
95
96 return MIRBuilder.buildFrameIndex(Res: LLT::pointer(AddressSpace: 0, SizeInBits: 32), Idx: FI).getReg(Idx: 0);
97}
98
99void MipsIncomingValueHandler::assignValueToAddress(
100 Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
101 const CCValAssign &VA) {
102 MachineFunction &MF = MIRBuilder.getMF();
103 auto MMO = MF.getMachineMemOperand(PtrInfo: MPO, F: MachineMemOperand::MOLoad, MemTy,
104 BaseAlignment: inferAlignFromPtrInfo(MF, MPO));
105 MIRBuilder.buildLoad(Res: ValVReg, Addr, MMO&: *MMO);
106}
107
108/// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom
109/// assignment because generic code assumes getNumRegistersForCallingConv is
110/// accurate. In this case it is not because the type/number are context
111/// dependent on other arguments.
112unsigned
113MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,
114 ArrayRef<CCValAssign> VAs,
115 std::function<void()> *Thunk) {
116 const CCValAssign &VALo = VAs[0];
117 const CCValAssign &VAHi = VAs[1];
118
119 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
120 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
121 "unexpected custom value");
122
123 auto CopyLo = MIRBuilder.buildCopy(Res: LLT::scalar(SizeInBits: 32), Op: VALo.getLocReg());
124 auto CopyHi = MIRBuilder.buildCopy(Res: LLT::scalar(SizeInBits: 32), Op: VAHi.getLocReg());
125 if (!STI.isLittle())
126 std::swap(a&: CopyLo, b&: CopyHi);
127
128 Arg.OrigRegs.assign(in_start: Arg.Regs.begin(), in_end: Arg.Regs.end());
129 Arg.Regs = { CopyLo.getReg(Idx: 0), CopyHi.getReg(Idx: 0) };
130 MIRBuilder.buildMergeLikeInstr(Res: Arg.OrigRegs[0], Ops: {CopyLo, CopyHi});
131
132 markPhysRegUsed(PhysReg: VALo.getLocReg());
133 markPhysRegUsed(PhysReg: VAHi.getLocReg());
134 return 2;
135}
136
137namespace {
138class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
139 const MipsSubtarget &STI;
140
141public:
142 MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder,
143 MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)
144 : OutgoingValueHandler(MIRBuilder, MRI),
145 STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()), MIB(MIB) {}
146
147private:
148 void assignValueToReg(Register ValVReg, Register PhysReg,
149 const CCValAssign &VA,
150 ISD::ArgFlagsTy Flags = {}) override;
151
152 Register getStackAddress(uint64_t Size, int64_t Offset,
153 MachinePointerInfo &MPO,
154 ISD::ArgFlagsTy Flags) override;
155
156 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
157 const MachinePointerInfo &MPO,
158 const CCValAssign &VA) override;
159 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
160 ArrayRef<CCValAssign> VAs,
161 std::function<void()> *Thunk) override;
162
163 MachineInstrBuilder &MIB;
164};
165} // end anonymous namespace
166
167void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg,
168 Register PhysReg,
169 const CCValAssign &VA,
170 ISD::ArgFlagsTy Flags) {
171 Register ExtReg = extendRegister(ValReg: ValVReg, VA);
172 MIRBuilder.buildCopy(Res: PhysReg, Op: ExtReg);
173 MIB.addUse(RegNo: PhysReg, Flags: RegState::Implicit);
174}
175
176Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size,
177 int64_t Offset,
178 MachinePointerInfo &MPO,
179 ISD::ArgFlagsTy Flags) {
180 MachineFunction &MF = MIRBuilder.getMF();
181 MPO = MachinePointerInfo::getStack(MF, Offset);
182
183 LLT p0 = LLT::pointer(AddressSpace: 0, SizeInBits: 32);
184 LLT s32 = LLT::scalar(SizeInBits: 32);
185 auto SPReg = MIRBuilder.buildCopy(Res: p0, Op: Register(Mips::SP));
186
187 auto OffsetReg = MIRBuilder.buildConstant(Res: s32, Val: Offset);
188 auto AddrReg = MIRBuilder.buildPtrAdd(Res: p0, Op0: SPReg, Op1: OffsetReg);
189 return AddrReg.getReg(Idx: 0);
190}
191
192void MipsOutgoingValueHandler::assignValueToAddress(
193 Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
194 const CCValAssign &VA) {
195 MachineFunction &MF = MIRBuilder.getMF();
196 uint64_t LocMemOffset = VA.getLocMemOffset();
197
198 auto MMO = MF.getMachineMemOperand(
199 PtrInfo: MPO, F: MachineMemOperand::MOStore, MemTy,
200 BaseAlignment: commonAlignment(A: STI.getStackAlignment(), Offset: LocMemOffset));
201
202 Register ExtReg = extendRegister(ValReg: ValVReg, VA);
203 MIRBuilder.buildStore(Val: ExtReg, Addr, MMO&: *MMO);
204}
205
206unsigned
207MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,
208 ArrayRef<CCValAssign> VAs,
209 std::function<void()> *Thunk) {
210 const CCValAssign &VALo = VAs[0];
211 const CCValAssign &VAHi = VAs[1];
212
213 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
214 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
215 "unexpected custom value");
216
217 auto Unmerge =
218 MIRBuilder.buildUnmerge(Res: {LLT::scalar(SizeInBits: 32), LLT::scalar(SizeInBits: 32)}, Op: Arg.Regs[0]);
219 Register Lo = Unmerge.getReg(Idx: 0);
220 Register Hi = Unmerge.getReg(Idx: 1);
221
222 Arg.OrigRegs.assign(in_start: Arg.Regs.begin(), in_end: Arg.Regs.end());
223 Arg.Regs = { Lo, Hi };
224 if (!STI.isLittle())
225 std::swap(a&: Lo, b&: Hi);
226
227 MIB.addUse(RegNo: VALo.getLocReg(), Flags: RegState::Implicit);
228 MIB.addUse(RegNo: VAHi.getLocReg(), Flags: RegState::Implicit);
229
230 // If we can return a thunk, just include the register copies. The unmerge can
231 // be emitted earlier.
232 if (Thunk) {
233 *Thunk = [=]() {
234 MIRBuilder.buildCopy(Res: VALo.getLocReg(), Op: Lo);
235 MIRBuilder.buildCopy(Res: VAHi.getLocReg(), Op: Hi);
236 };
237 return 2;
238 }
239 MIRBuilder.buildCopy(Res: VALo.getLocReg(), Op: Lo);
240 MIRBuilder.buildCopy(Res: VAHi.getLocReg(), Op: Hi);
241 return 2;
242}
243
244static bool isSupportedArgumentType(Type *T) {
245 if (T->isIntegerTy())
246 return true;
247 if (T->isPointerTy())
248 return true;
249 if (T->isFloatingPointTy())
250 return true;
251 return false;
252}
253
254static bool isSupportedReturnType(Type *T) {
255 if (T->isIntegerTy())
256 return true;
257 if (T->isPointerTy())
258 return true;
259 if (T->isFloatingPointTy())
260 return true;
261 if (T->isAggregateType())
262 return true;
263 return false;
264}
265
266bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
267 const Value *Val, ArrayRef<Register> VRegs,
268 FunctionLoweringInfo &FLI) const {
269
270 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Opcode: Mips::RetRA);
271
272 if (Val != nullptr && !isSupportedReturnType(T: Val->getType()))
273 return false;
274
275 if (!VRegs.empty()) {
276 MachineFunction &MF = MIRBuilder.getMF();
277 const Function &F = MF.getFunction();
278 const DataLayout &DL = MF.getDataLayout();
279 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
280
281 SmallVector<ArgInfo, 8> RetInfos;
282
283 ArgInfo ArgRetInfo(VRegs, *Val, 0);
284 setArgFlags(Arg&: ArgRetInfo, OpIdx: AttributeList::ReturnIndex, DL, FuncInfo: F);
285 splitToValueTypes(OrigArgInfo: ArgRetInfo, SplitArgs&: RetInfos, DL, CallConv: F.getCallingConv());
286
287 SmallVector<CCValAssign, 16> ArgLocs;
288
289 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
290 F.getContext());
291
292 MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
293 OutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn());
294
295 if (!determineAssignments(Assigner, Args&: RetInfos, CCInfo))
296 return false;
297
298 if (!handleAssignments(Handler&: RetHandler, Args&: RetInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
299 return false;
300 }
301
302 MIRBuilder.insertInstr(MIB: Ret);
303 return true;
304}
305
306bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
307 const Function &F,
308 ArrayRef<ArrayRef<Register>> VRegs,
309 FunctionLoweringInfo &FLI) const {
310
311 // Quick exit if there aren't any args.
312 if (F.arg_empty())
313 return true;
314
315 for (auto &Arg : F.args()) {
316 if (!isSupportedArgumentType(T: Arg.getType()))
317 return false;
318 }
319
320 MachineFunction &MF = MIRBuilder.getMF();
321 const DataLayout &DL = MF.getDataLayout();
322 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
323
324 SmallVector<ArgInfo, 8> ArgInfos;
325 unsigned i = 0;
326 for (auto &Arg : F.args()) {
327 ArgInfo AInfo(VRegs[i], Arg, i);
328 setArgFlags(Arg&: AInfo, OpIdx: i + AttributeList::FirstArgIndex, DL, FuncInfo: F);
329
330 splitToValueTypes(OrigArgInfo: AInfo, SplitArgs&: ArgInfos, DL, CallConv: F.getCallingConv());
331 ++i;
332 }
333
334 SmallVector<CCValAssign, 16> ArgLocs;
335 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
336 F.getContext());
337
338 const MipsABIInfo &ABI = MF.getSubtarget<MipsSubtarget>().getABI();
339 CCInfo.AllocateStack(Size: ABI.GetCalleeAllocdArgSizeInBytes(CC: F.getCallingConv()),
340 Alignment: Align(1));
341
342 IncomingValueAssigner Assigner(TLI.CCAssignFnForCall());
343 if (!determineAssignments(Assigner, Args&: ArgInfos, CCInfo))
344 return false;
345
346 MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
347 if (!handleAssignments(Handler, Args&: ArgInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
348 return false;
349
350 if (F.isVarArg()) {
351 ArrayRef<MCPhysReg> ArgRegs =
352 ABI.getVarArgRegs(isGP64bit: MF.getSubtarget<MipsSubtarget>().isGP64bit());
353 unsigned Idx = CCInfo.getFirstUnallocated(Regs: ArgRegs);
354
355 int VaArgOffset;
356 unsigned RegSize = 4;
357 if (ArgRegs.size() == Idx)
358 VaArgOffset = alignTo(Value: CCInfo.getStackSize(), Align: RegSize);
359 else {
360 VaArgOffset =
361 (int)ABI.GetCalleeAllocdArgSizeInBytes(CC: CCInfo.getCallingConv()) -
362 (int)(RegSize * (ArgRegs.size() - Idx));
363 }
364
365 MachineFrameInfo &MFI = MF.getFrameInfo();
366 int FI = MFI.CreateFixedObject(Size: RegSize, SPOffset: VaArgOffset, IsImmutable: true);
367 MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
368
369 for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
370 MIRBuilder.getMBB().addLiveIn(PhysReg: ArgRegs[I]);
371 LLT RegTy = LLT::scalar(SizeInBits: RegSize * 8);
372 MachineInstrBuilder Copy =
373 MIRBuilder.buildCopy(Res: RegTy, Op: Register(ArgRegs[I]));
374 FI = MFI.CreateFixedObject(Size: RegSize, SPOffset: VaArgOffset, IsImmutable: true);
375 MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
376
377 const LLT PtrTy = LLT::pointer(AddressSpace: MPO.getAddrSpace(), SizeInBits: 32);
378 auto FrameIndex = MIRBuilder.buildFrameIndex(Res: PtrTy, Idx: FI);
379 MachineMemOperand *MMO = MF.getMachineMemOperand(
380 PtrInfo: MPO, F: MachineMemOperand::MOStore, MemTy: RegTy, BaseAlignment: Align(RegSize));
381 MIRBuilder.buildStore(Val: Copy, Addr: FrameIndex, MMO&: *MMO);
382 }
383 }
384
385 return true;
386}
387
388bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
389 CallLoweringInfo &Info) const {
390
391 if (Info.CallConv != CallingConv::C)
392 return false;
393
394 for (auto &Arg : Info.OrigArgs) {
395 if (!isSupportedArgumentType(T: Arg.Ty))
396 return false;
397 if (Arg.Flags[0].isByVal())
398 return false;
399 if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())
400 return false;
401 }
402
403 if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(T: Info.OrigRet.Ty))
404 return false;
405
406 MachineFunction &MF = MIRBuilder.getMF();
407 const Function &F = MF.getFunction();
408 const DataLayout &DL = MF.getDataLayout();
409 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
410 const MipsTargetMachine &TM =
411 static_cast<const MipsTargetMachine &>(MF.getTarget());
412 const MipsABIInfo &ABI = MF.getSubtarget<MipsSubtarget>().getABI();
413
414 MachineInstrBuilder CallSeqStart =
415 MIRBuilder.buildInstr(Opcode: Mips::ADJCALLSTACKDOWN);
416
417 const bool IsCalleeGlobalPIC =
418 Info.Callee.isGlobal() && TM.isPositionIndependent();
419
420 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
421 Opcode: Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
422 MIB.setOperandDead(0); // implicit-def $ra
423 MIB.addDef(RegNo: Mips::SP, Flags: RegState::Implicit);
424 if (IsCalleeGlobalPIC) {
425 Register CalleeReg =
426 MF.getRegInfo().createGenericVirtualRegister(Ty: LLT::pointer(AddressSpace: 0, SizeInBits: 32));
427 MachineInstr *CalleeGlobalValue =
428 MIRBuilder.buildGlobalValue(Res: CalleeReg, GV: Info.Callee.getGlobal());
429 if (!Info.Callee.getGlobal()->hasLocalLinkage())
430 CalleeGlobalValue->getOperand(i: 1).setTargetFlags(MipsII::MO_GOT_CALL);
431 MIB.addUse(RegNo: CalleeReg);
432 } else
433 MIB.add(MO: Info.Callee);
434 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
435 MIB.addRegMask(Mask: TRI->getCallPreservedMask(MF, Info.CallConv));
436
437 TargetLowering::ArgListTy FuncOrigArgs;
438 FuncOrigArgs.reserve(n: Info.OrigArgs.size());
439
440 SmallVector<ArgInfo, 8> ArgInfos;
441 for (auto &Arg : Info.OrigArgs)
442 splitToValueTypes(OrigArgInfo: Arg, SplitArgs&: ArgInfos, DL, CallConv: Info.CallConv);
443
444 SmallVector<CCValAssign, 8> ArgLocs;
445 bool IsCalleeVarArg = false;
446 if (Info.Callee.isGlobal()) {
447 const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
448 IsCalleeVarArg = CF->isVarArg();
449 }
450
451 // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it
452 // depends on looking directly at the call target.
453 MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs,
454 F.getContext());
455
456 CCInfo.AllocateStack(Size: ABI.GetCalleeAllocdArgSizeInBytes(CC: Info.CallConv),
457 Alignment: Align(1));
458
459 OutgoingValueAssigner Assigner(TLI.CCAssignFnForCall());
460 if (!determineAssignments(Assigner, Args&: ArgInfos, CCInfo))
461 return false;
462
463 MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB);
464 if (!handleAssignments(Handler&: ArgHandler, Args&: ArgInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
465 return false;
466
467 unsigned StackSize = CCInfo.getStackSize();
468 unsigned StackAlignment = F.getParent()->getOverrideStackAlignment();
469 if (!StackAlignment) {
470 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
471 StackAlignment = TFL->getStackAlignment();
472 }
473 StackSize = alignTo(Value: StackSize, Align: StackAlignment);
474 CallSeqStart.addImm(Val: StackSize).addImm(Val: 0);
475
476 if (IsCalleeGlobalPIC) {
477 MIRBuilder.buildCopy(
478 Res: Register(Mips::GP),
479 Op: MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));
480 MIB.addUse(RegNo: Mips::GP, Flags: RegState::Implicit);
481 }
482 MIRBuilder.insertInstr(MIB);
483 if (MIB->getOpcode() == Mips::JALRPseudo) {
484 const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>();
485 MIB.constrainAllUses(TII: MIRBuilder.getTII(), TRI: *STI.getRegisterInfo(),
486 RBI: *STI.getRegBankInfo());
487 }
488
489 if (!Info.OrigRet.Ty->isVoidTy()) {
490 ArgInfos.clear();
491
492 CallLowering::splitToValueTypes(OrigArgInfo: Info.OrigRet, SplitArgs&: ArgInfos, DL,
493 CallConv: F.getCallingConv());
494
495 SmallVector<CCValAssign, 8> ArgLocs;
496 IncomingValueAssigner Assigner(TLI.CCAssignFnForReturn());
497 CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
498
499 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
500 F.getContext());
501
502 if (!determineAssignments(Assigner, Args&: ArgInfos, CCInfo))
503 return false;
504
505 if (!handleAssignments(Handler&: RetHandler, Args&: ArgInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
506 return false;
507 }
508
509 MIRBuilder.buildInstr(Opcode: Mips::ADJCALLSTACKUP).addImm(Val: StackSize).addImm(Val: 0);
510
511 return true;
512}
513