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 base_alignment: 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 base_alignment: 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 // If we can return a thunk, just include the register copies. The unmerge can
228 // be emitted earlier.
229 if (Thunk) {
230 *Thunk = [=]() {
231 MIRBuilder.buildCopy(Res: VALo.getLocReg(), Op: Lo);
232 MIRBuilder.buildCopy(Res: VAHi.getLocReg(), Op: Hi);
233 };
234 return 2;
235 }
236 MIRBuilder.buildCopy(Res: VALo.getLocReg(), Op: Lo);
237 MIRBuilder.buildCopy(Res: VAHi.getLocReg(), Op: Hi);
238 return 2;
239}
240
241static bool isSupportedArgumentType(Type *T) {
242 if (T->isIntegerTy())
243 return true;
244 if (T->isPointerTy())
245 return true;
246 if (T->isFloatingPointTy())
247 return true;
248 return false;
249}
250
251static bool isSupportedReturnType(Type *T) {
252 if (T->isIntegerTy())
253 return true;
254 if (T->isPointerTy())
255 return true;
256 if (T->isFloatingPointTy())
257 return true;
258 if (T->isAggregateType())
259 return true;
260 return false;
261}
262
263bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
264 const Value *Val, ArrayRef<Register> VRegs,
265 FunctionLoweringInfo &FLI) const {
266
267 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Opcode: Mips::RetRA);
268
269 if (Val != nullptr && !isSupportedReturnType(T: Val->getType()))
270 return false;
271
272 if (!VRegs.empty()) {
273 MachineFunction &MF = MIRBuilder.getMF();
274 const Function &F = MF.getFunction();
275 const DataLayout &DL = MF.getDataLayout();
276 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
277
278 SmallVector<ArgInfo, 8> RetInfos;
279
280 ArgInfo ArgRetInfo(VRegs, *Val, 0);
281 setArgFlags(Arg&: ArgRetInfo, OpIdx: AttributeList::ReturnIndex, DL, FuncInfo: F);
282 splitToValueTypes(OrigArgInfo: ArgRetInfo, SplitArgs&: RetInfos, DL, CallConv: F.getCallingConv());
283
284 SmallVector<CCValAssign, 16> ArgLocs;
285
286 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
287 F.getContext());
288
289 MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
290 OutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn());
291
292 if (!determineAssignments(Assigner, Args&: RetInfos, CCInfo))
293 return false;
294
295 if (!handleAssignments(Handler&: RetHandler, Args&: RetInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
296 return false;
297 }
298
299 MIRBuilder.insertInstr(MIB: Ret);
300 return true;
301}
302
303bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
304 const Function &F,
305 ArrayRef<ArrayRef<Register>> VRegs,
306 FunctionLoweringInfo &FLI) const {
307
308 // Quick exit if there aren't any args.
309 if (F.arg_empty())
310 return true;
311
312 for (auto &Arg : F.args()) {
313 if (!isSupportedArgumentType(T: Arg.getType()))
314 return false;
315 }
316
317 MachineFunction &MF = MIRBuilder.getMF();
318 const DataLayout &DL = MF.getDataLayout();
319 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
320
321 SmallVector<ArgInfo, 8> ArgInfos;
322 unsigned i = 0;
323 for (auto &Arg : F.args()) {
324 ArgInfo AInfo(VRegs[i], Arg, i);
325 setArgFlags(Arg&: AInfo, OpIdx: i + AttributeList::FirstArgIndex, DL, FuncInfo: F);
326
327 splitToValueTypes(OrigArgInfo: AInfo, SplitArgs&: ArgInfos, DL, CallConv: F.getCallingConv());
328 ++i;
329 }
330
331 SmallVector<CCValAssign, 16> ArgLocs;
332 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
333 F.getContext());
334
335 const MipsTargetMachine &TM =
336 static_cast<const MipsTargetMachine &>(MF.getTarget());
337 const MipsABIInfo &ABI = TM.getABI();
338 CCInfo.AllocateStack(Size: ABI.GetCalleeAllocdArgSizeInBytes(CC: F.getCallingConv()),
339 Alignment: Align(1));
340
341 IncomingValueAssigner Assigner(TLI.CCAssignFnForCall());
342 if (!determineAssignments(Assigner, Args&: ArgInfos, CCInfo))
343 return false;
344
345 MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
346 if (!handleAssignments(Handler, Args&: ArgInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
347 return false;
348
349 if (F.isVarArg()) {
350 ArrayRef<MCPhysReg> ArgRegs =
351 ABI.getVarArgRegs(isGP64bit: MF.getSubtarget<MipsSubtarget>().isGP64bit());
352 unsigned Idx = CCInfo.getFirstUnallocated(Regs: ArgRegs);
353
354 int VaArgOffset;
355 unsigned RegSize = 4;
356 if (ArgRegs.size() == Idx)
357 VaArgOffset = alignTo(Value: CCInfo.getStackSize(), Align: RegSize);
358 else {
359 VaArgOffset =
360 (int)ABI.GetCalleeAllocdArgSizeInBytes(CC: CCInfo.getCallingConv()) -
361 (int)(RegSize * (ArgRegs.size() - Idx));
362 }
363
364 MachineFrameInfo &MFI = MF.getFrameInfo();
365 int FI = MFI.CreateFixedObject(Size: RegSize, SPOffset: VaArgOffset, IsImmutable: true);
366 MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
367
368 for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
369 MIRBuilder.getMBB().addLiveIn(PhysReg: ArgRegs[I]);
370 LLT RegTy = LLT::scalar(SizeInBits: RegSize * 8);
371 MachineInstrBuilder Copy =
372 MIRBuilder.buildCopy(Res: RegTy, Op: Register(ArgRegs[I]));
373 FI = MFI.CreateFixedObject(Size: RegSize, SPOffset: VaArgOffset, IsImmutable: true);
374 MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
375
376 const LLT PtrTy = LLT::pointer(AddressSpace: MPO.getAddrSpace(), SizeInBits: 32);
377 auto FrameIndex = MIRBuilder.buildFrameIndex(Res: PtrTy, Idx: FI);
378 MachineMemOperand *MMO = MF.getMachineMemOperand(
379 PtrInfo: MPO, f: MachineMemOperand::MOStore, MemTy: RegTy, base_alignment: Align(RegSize));
380 MIRBuilder.buildStore(Val: Copy, Addr: FrameIndex, MMO&: *MMO);
381 }
382 }
383
384 return true;
385}
386
387bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
388 CallLoweringInfo &Info) const {
389
390 if (Info.CallConv != CallingConv::C)
391 return false;
392
393 for (auto &Arg : Info.OrigArgs) {
394 if (!isSupportedArgumentType(T: Arg.Ty))
395 return false;
396 if (Arg.Flags[0].isByVal())
397 return false;
398 if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())
399 return false;
400 }
401
402 if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(T: Info.OrigRet.Ty))
403 return false;
404
405 MachineFunction &MF = MIRBuilder.getMF();
406 const Function &F = MF.getFunction();
407 const DataLayout &DL = MF.getDataLayout();
408 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
409 const MipsTargetMachine &TM =
410 static_cast<const MipsTargetMachine &>(MF.getTarget());
411 const MipsABIInfo &ABI = TM.getABI();
412
413 MachineInstrBuilder CallSeqStart =
414 MIRBuilder.buildInstr(Opcode: Mips::ADJCALLSTACKDOWN);
415
416 const bool IsCalleeGlobalPIC =
417 Info.Callee.isGlobal() && TM.isPositionIndependent();
418
419 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
420 Opcode: Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
421 MIB.addDef(RegNo: Mips::SP, Flags: RegState::Implicit);
422 if (IsCalleeGlobalPIC) {
423 Register CalleeReg =
424 MF.getRegInfo().createGenericVirtualRegister(Ty: LLT::pointer(AddressSpace: 0, SizeInBits: 32));
425 MachineInstr *CalleeGlobalValue =
426 MIRBuilder.buildGlobalValue(Res: CalleeReg, GV: Info.Callee.getGlobal());
427 if (!Info.Callee.getGlobal()->hasLocalLinkage())
428 CalleeGlobalValue->getOperand(i: 1).setTargetFlags(MipsII::MO_GOT_CALL);
429 MIB.addUse(RegNo: CalleeReg);
430 } else
431 MIB.add(MO: Info.Callee);
432 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
433 MIB.addRegMask(Mask: TRI->getCallPreservedMask(MF, Info.CallConv));
434
435 TargetLowering::ArgListTy FuncOrigArgs;
436 FuncOrigArgs.reserve(n: Info.OrigArgs.size());
437
438 SmallVector<ArgInfo, 8> ArgInfos;
439 for (auto &Arg : Info.OrigArgs)
440 splitToValueTypes(OrigArgInfo: Arg, SplitArgs&: ArgInfos, DL, CallConv: Info.CallConv);
441
442 SmallVector<CCValAssign, 8> ArgLocs;
443 bool IsCalleeVarArg = false;
444 if (Info.Callee.isGlobal()) {
445 const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
446 IsCalleeVarArg = CF->isVarArg();
447 }
448
449 // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it
450 // depends on looking directly at the call target.
451 MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs,
452 F.getContext());
453
454 CCInfo.AllocateStack(Size: ABI.GetCalleeAllocdArgSizeInBytes(CC: Info.CallConv),
455 Alignment: Align(1));
456
457 OutgoingValueAssigner Assigner(TLI.CCAssignFnForCall());
458 if (!determineAssignments(Assigner, Args&: ArgInfos, CCInfo))
459 return false;
460
461 MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB);
462 if (!handleAssignments(Handler&: ArgHandler, Args&: ArgInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
463 return false;
464
465 unsigned StackSize = CCInfo.getStackSize();
466 unsigned StackAlignment = F.getParent()->getOverrideStackAlignment();
467 if (!StackAlignment) {
468 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
469 StackAlignment = TFL->getStackAlignment();
470 }
471 StackSize = alignTo(Value: StackSize, Align: StackAlignment);
472 CallSeqStart.addImm(Val: StackSize).addImm(Val: 0);
473
474 if (IsCalleeGlobalPIC) {
475 MIRBuilder.buildCopy(
476 Res: Register(Mips::GP),
477 Op: MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));
478 MIB.addDef(RegNo: Mips::GP, Flags: RegState::Implicit);
479 }
480 MIRBuilder.insertInstr(MIB);
481 if (MIB->getOpcode() == Mips::JALRPseudo) {
482 const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>();
483 MIB.constrainAllUses(TII: MIRBuilder.getTII(), TRI: *STI.getRegisterInfo(),
484 RBI: *STI.getRegBankInfo());
485 }
486
487 if (!Info.OrigRet.Ty->isVoidTy()) {
488 ArgInfos.clear();
489
490 CallLowering::splitToValueTypes(OrigArgInfo: Info.OrigRet, SplitArgs&: ArgInfos, DL,
491 CallConv: F.getCallingConv());
492
493 SmallVector<CCValAssign, 8> ArgLocs;
494 IncomingValueAssigner Assigner(TLI.CCAssignFnForReturn());
495 CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
496
497 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
498 F.getContext());
499
500 if (!determineAssignments(Assigner, Args&: ArgInfos, CCInfo))
501 return false;
502
503 if (!handleAssignments(Handler&: RetHandler, Args&: ArgInfos, CCState&: CCInfo, ArgLocs, MIRBuilder))
504 return false;
505 }
506
507 MIRBuilder.buildInstr(Opcode: Mips::ADJCALLSTACKUP).addImm(Val: StackSize).addImm(Val: 0);
508
509 return true;
510}
511