• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef MAPLE_IR_INCLUDE_MIR_NODES_H
17 #define MAPLE_IR_INCLUDE_MIR_NODES_H
18 #include <sstream>
19 #include <utility>
20 #include <atomic>
21 #include "opcodes.h"
22 #include "opcode_info.h"
23 #include "mir_type.h"
24 #include "cmpl.h"
25 #include "mir_module.h"
26 #include "mir_const.h"
27 #include "maple_string.h"
28 #include "src_position.h"
29 #include "ptr_list_ref.h"
30 
31 namespace maple {
32 constexpr size_t kFirstOpnd = 0;
33 constexpr size_t kSecondOpnd = 1;
34 constexpr size_t kThirdOpnd = 2;
35 constexpr size_t kFourthOpnd = 3;
36 constexpr size_t kOpndNum = 3;
37 
38 extern MIRModule *theMIRModule;
39 extern void EmitStr(const MapleString &mplStr);
40 
41 class MIRPregTable;  // circular dependency exists, no other choice
42 class TypeTable;     // circular dependency exists, no other choice
43 class VerifyResult;  // circular dependency exists, no other choice
44 
45 struct RegFieldPair {
46 public:
47     RegFieldPair() = default;
48 
RegFieldPairRegFieldPair49     RegFieldPair(FieldID fidx, PregIdx pidx) : fieldID(fidx), pregIdx(pidx) {}
50 
IsRegRegFieldPair51     bool IsReg() const
52     {
53         return pregIdx > 0;
54     }
55 
GetFieldIDRegFieldPair56     FieldID GetFieldID() const
57     {
58         return fieldID;
59     }
60 
GetPregIdxRegFieldPair61     PregIdx GetPregIdx() const
62     {
63         return pregIdx;
64     }
65 
SetFieldIDRegFieldPair66     void SetFieldID(FieldID fld)
67     {
68         fieldID = fld;
69     }
70 
SetPregIdxRegFieldPair71     void SetPregIdx(PregIdx idx)
72     {
73         pregIdx = idx;
74     }
75 
76 private:
77     FieldID fieldID = 0;
78     PregIdx pregIdx = 0;
79 };
80 
81 using CallReturnPair = std::pair<StIdx, RegFieldPair>;
82 using CallReturnVector = MapleVector<CallReturnPair>;
83 // Made public so that other modules (such as maplebe) can print intrinsic names
84 // in debug information or comments in assembly files.
85 const char *GetIntrinsicName(MIRIntrinsicID intrn);
86 class BaseNode : public BaseNodeT {
87 public:
BaseNode(Opcode o)88     explicit BaseNode(Opcode o)
89     {
90         op = o;
91         ptyp = kPtyInvalid;
92         typeFlag = 0;
93         numOpnds = 0;
94     }
95 
BaseNode(Opcode o,uint8 numOpr)96     BaseNode(Opcode o, uint8 numOpr)
97     {
98         op = o;
99         ptyp = kPtyInvalid;
100         typeFlag = 0;
101         numOpnds = numOpr;
102     }
103 
BaseNode(const Opcode o,const PrimType typ,uint8 numOpr)104     BaseNode(const Opcode o, const PrimType typ, uint8 numOpr)
105     {
106         op = o;
107         ptyp = typ;
108         typeFlag = 0;
109         numOpnds = numOpr;
110     }
111 
112     virtual ~BaseNode() = default;
113 
CloneTree(MapleAllocator & allocator)114     virtual BaseNode *CloneTree(MapleAllocator &allocator) const
115     {
116         return allocator.GetMemPool()->New<BaseNode>(*this);
117     }
118 
119     virtual void DumpBase(int32 indent) const;
120 
Dump(int32 indent)121     virtual void Dump(int32 indent) const
122     {
123         DumpBase(indent);
124     }
125 
Dump()126     void Dump() const
127     {
128         Dump(0);
129         LogInfo::MapleLogger() << '\n';
130     }
131 
SizeOfInstr()132     virtual uint8 SizeOfInstr() const
133     {
134         return kOpcodeInfo.GetTableItemAt(GetOpCode()).instrucSize;
135     }
136 
137     const char *GetOpName() const;
138     bool MayThrowException();
NumOpnds()139     virtual size_t NumOpnds() const
140     {
141         return numOpnds;
142     }
143 
Opnd(size_t)144     virtual BaseNode *Opnd(size_t) const
145     {
146         DEBUG_ASSERT(0, "override needed");
147         return nullptr;
148     }
149 
SetOpnd(BaseNode *,size_t)150     virtual void SetOpnd(BaseNode *, size_t)
151     {
152         DEBUG_ASSERT(0, "This should not happen");
153     }
154 
IsLeaf()155     virtual bool IsLeaf() const
156     {
157         return true;
158     }
159 
GetCallReturnVector()160     virtual CallReturnVector *GetCallReturnVector()
161     {
162         return nullptr;
163     }
164 
GetCallReturnType()165     virtual MIRType *GetCallReturnType()
166     {
167         return nullptr;
168     }
169 
IsUnaryNode()170     virtual bool IsUnaryNode() const
171     {
172         return false;
173     }
174 
IsBinaryNode()175     virtual bool IsBinaryNode() const
176     {
177         return false;
178     }
179 
IsTernaryNode()180     virtual bool IsTernaryNode() const
181     {
182         return false;
183     }
184 
IsNaryNode()185     virtual bool IsNaryNode() const
186     {
187         return false;
188     }
189 
IsCondBr()190     bool IsCondBr() const
191     {
192         return kOpcodeInfo.IsCondBr(GetOpCode());
193     }
194 
IsConstval()195     bool IsConstval() const
196     {
197         return op == OP_constval;
198     }
199 
Verify()200     virtual bool Verify() const
201     {
202         return true;
203     }
204 
Verify(VerifyResult &)205     virtual bool Verify(VerifyResult &) const
206     {
207         return Verify();
208     }
209 
IsSSANode()210     virtual bool IsSSANode() const
211     {
212         return false;
213     }
214 
IsSameContent(const BaseNode * node)215     virtual bool IsSameContent(const BaseNode *node) const
216     {
217         return false;
218     }
219 };
220 
221 class UnaryNode : public BaseNode {
222 public:
UnaryNode(Opcode o)223     explicit UnaryNode(Opcode o) : BaseNode(o, 1) {}
224 
UnaryNode(Opcode o,PrimType typ)225     UnaryNode(Opcode o, PrimType typ) : BaseNode(o, typ, 1) {}
226 
UnaryNode(Opcode o,PrimType typ,BaseNode * expr)227     UnaryNode(Opcode o, PrimType typ, BaseNode *expr) : BaseNode(o, typ, 1), uOpnd(expr) {}
228 
229     virtual ~UnaryNode() override = default;
230 
231     void DumpOpnd(const MIRModule &mod, int32 indent) const;
232     void DumpOpnd(int32 indent) const;
233     void Dump(int32 indent) const override;
234     bool Verify() const override;
235 
Verify(VerifyResult &)236     bool Verify(VerifyResult &) const override
237     {
238         return Verify();
239     }
240 
CloneTree(MapleAllocator & allocator)241     UnaryNode *CloneTree(MapleAllocator &allocator) const override
242     {
243         auto *node = allocator.GetMemPool()->New<UnaryNode>(*this);
244         node->SetOpnd(uOpnd->CloneTree(allocator), 0);
245         return node;
246     }
247 
Opnd(size_t)248     BaseNode *Opnd(size_t) const override
249     {
250         return uOpnd;
251     }
252 
NumOpnds()253     size_t NumOpnds() const override
254     {
255         return 1;
256     }
257 
SetOpnd(BaseNode * node,size_t)258     void SetOpnd(BaseNode *node, size_t) override
259     {
260         uOpnd = node;
261     }
262 
IsLeaf()263     bool IsLeaf() const override
264     {
265         return false;
266     }
267 
IsUnaryNode()268     bool IsUnaryNode() const override
269     {
270         return true;
271     }
272 
273     bool IsSameContent(const BaseNode *node) const override;
274 
275 private:
276     BaseNode *uOpnd = nullptr;
277 };
278 
279 class TypeCvtNode : public UnaryNode {
280 public:
TypeCvtNode(Opcode o)281     explicit TypeCvtNode(Opcode o) : UnaryNode(o) {}
282 
TypeCvtNode(Opcode o,PrimType typ)283     TypeCvtNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
284 
TypeCvtNode(Opcode o,PrimType typ,PrimType fromtyp,BaseNode * expr)285     TypeCvtNode(Opcode o, PrimType typ, PrimType fromtyp, BaseNode *expr)
286         : UnaryNode(o, typ, expr), fromPrimType(fromtyp)
287     {
288     }
289 
290     virtual ~TypeCvtNode() = default;
291 
292     void Dump(int32 indent) const override;
293     bool Verify() const override;
294 
Verify(VerifyResult &)295     bool Verify(VerifyResult &) const override
296     {
297         return Verify();
298     }
299 
CloneTree(MapleAllocator & allocator)300     TypeCvtNode *CloneTree(MapleAllocator &allocator) const override
301     {
302         auto *node = allocator.GetMemPool()->New<TypeCvtNode>(*this);
303         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
304         return node;
305     }
306 
FromType()307     PrimType FromType() const
308     {
309         return fromPrimType;
310     }
311 
SetFromType(PrimType from)312     void SetFromType(PrimType from)
313     {
314         fromPrimType = from;
315     }
316 
317     bool IsSameContent(const BaseNode *node) const override;
318 
319 private:
320     PrimType fromPrimType = kPtyInvalid;
321 };
322 
323 // used for retype
324 class RetypeNode : public TypeCvtNode {
325 public:
RetypeNode()326     RetypeNode() : TypeCvtNode(OP_retype) {}
327 
RetypeNode(PrimType typ)328     explicit RetypeNode(PrimType typ) : TypeCvtNode(OP_retype, typ) {}
329 
RetypeNode(PrimType typ,PrimType fromtyp,TyIdx idx,BaseNode * expr)330     RetypeNode(PrimType typ, PrimType fromtyp, TyIdx idx, BaseNode *expr)
331         : TypeCvtNode(OP_retype, typ, fromtyp, expr), tyIdx(idx)
332     {
333     }
334 
335     virtual ~RetypeNode() = default;
336     void Dump(int32 indent) const override;
337     bool Verify(VerifyResult &verifyResult) const override;
338 
CloneTree(MapleAllocator & allocator)339     RetypeNode *CloneTree(MapleAllocator &allocator) const override
340     {
341         auto *node = allocator.GetMemPool()->New<RetypeNode>(*this);
342         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
343         return node;
344     }
345 
GetTyIdx()346     const TyIdx &GetTyIdx() const
347     {
348         return tyIdx;
349     }
350 
SetTyIdx(const TyIdx tyIdxVal)351     void SetTyIdx(const TyIdx tyIdxVal)
352     {
353         tyIdx = tyIdxVal;
354     }
355 
356 private:
357     bool VerifyPrimTypesAndOpnd() const;
358     bool CheckFromJarray(const MIRType &from, const MIRType &to, VerifyResult &verifyResult) const;
359     bool VerifyCompleteMIRType(const MIRType &from, const MIRType &to, bool isJavaRefType,
360                                VerifyResult &verifyResult) const;
361     bool VerifyJarrayDimention(const MIRJarrayType &from, const MIRJarrayType &to, VerifyResult &verifyResult) const;
362     bool IsJavaAssignable(const MIRType &from, const MIRType &to, VerifyResult &verifyResult) const;
363 
BothPointerOrJarray(const MIRType & from,const MIRType & to)364     bool BothPointerOrJarray(const MIRType &from, const MIRType &to) const
365     {
366         if (from.GetKind() != to.GetKind()) {
367             return false;
368         }
369         return from.IsMIRPtrType() || from.IsMIRJarrayType();
370     }
371 
IsInterfaceOrClass(const MIRType & mirType)372     bool IsInterfaceOrClass(const MIRType &mirType) const
373     {
374         return mirType.IsMIRClassType() || mirType.IsMIRInterfaceType();
375     }
376 
IsJavaRefType(const MIRType & mirType)377     bool IsJavaRefType(const MIRType &mirType) const
378     {
379         return mirType.IsMIRJarrayType() || mirType.IsMIRClassType() || mirType.IsMIRInterfaceType();
380     }
381 
382     TyIdx tyIdx = TyIdx(0);
383 };
384 
385 // used for extractbits, sext, zext
386 class ExtractbitsNode : public UnaryNode {
387 public:
ExtractbitsNode(Opcode o)388     explicit ExtractbitsNode(Opcode o) : UnaryNode(o) {}
389 
ExtractbitsNode(Opcode o,PrimType typ)390     ExtractbitsNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
391 
ExtractbitsNode(Opcode o,PrimType typ,uint8 offset,uint8 size)392     ExtractbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size)
393         : UnaryNode(o, typ), bitsOffset(offset), bitsSize(size)
394     {
395     }
396 
ExtractbitsNode(Opcode o,PrimType typ,uint8 offset,uint8 size,BaseNode * expr)397     ExtractbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size, BaseNode *expr)
398         : UnaryNode(o, typ, expr), bitsOffset(offset), bitsSize(size)
399     {
400     }
401 
402     virtual ~ExtractbitsNode() = default;
403 
404     void Dump(int32 indent) const override;
405     bool Verify() const override;
406 
CloneTree(MapleAllocator & allocator)407     ExtractbitsNode *CloneTree(MapleAllocator &allocator) const override
408     {
409         auto *node = allocator.GetMemPool()->New<ExtractbitsNode>(*this);
410         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
411         return node;
412     }
413 
GetBitsOffset()414     uint8 GetBitsOffset() const
415     {
416         return bitsOffset;
417     }
418 
SetBitsOffset(uint8 offset)419     void SetBitsOffset(uint8 offset)
420     {
421         bitsOffset = offset;
422     }
423 
GetBitsSize()424     uint8 GetBitsSize() const
425     {
426         return bitsSize;
427     }
428 
SetBitsSize(uint8 size)429     void SetBitsSize(uint8 size)
430     {
431         bitsSize = size;
432     }
433 
434 private:
435     uint8 bitsOffset = 0;
436     uint8 bitsSize = 0;
437 };
438 
439 class GCMallocNode : public BaseNode {
440 public:
GCMallocNode(Opcode o)441     explicit GCMallocNode(Opcode o) : BaseNode(o) {}
442 
GCMallocNode(Opcode o,PrimType typ,TyIdx tIdx)443     GCMallocNode(Opcode o, PrimType typ, TyIdx tIdx) : BaseNode(o, typ, 0), tyIdx(tIdx) {}
444 
445     virtual ~GCMallocNode() = default;
446 
447     void Dump(int32 indent) const override;
448 
CloneTree(MapleAllocator & allocator)449     GCMallocNode *CloneTree(MapleAllocator &allocator) const override
450     {
451         auto *node = allocator.GetMemPool()->New<GCMallocNode>(*this);
452         return node;
453     }
454 
GetTyIdx()455     TyIdx GetTyIdx() const
456     {
457         return tyIdx;
458     }
459 
SetTyIdx(TyIdx idx)460     void SetTyIdx(TyIdx idx)
461     {
462         tyIdx = idx;
463     }
464 
SetOrigPType(PrimType type)465     void SetOrigPType(PrimType type)
466     {
467         origPrimType = type;
468     }
469 
470 private:
471     TyIdx tyIdx = TyIdx(0);
472     PrimType origPrimType = kPtyInvalid;
473 };
474 
475 class JarrayMallocNode : public UnaryNode {
476 public:
JarrayMallocNode(Opcode o)477     explicit JarrayMallocNode(Opcode o) : UnaryNode(o) {}
478 
JarrayMallocNode(Opcode o,PrimType typ)479     JarrayMallocNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
480 
JarrayMallocNode(Opcode o,PrimType typ,TyIdx typeIdx)481     JarrayMallocNode(Opcode o, PrimType typ, TyIdx typeIdx) : UnaryNode(o, typ), tyIdx(typeIdx) {}
482 
JarrayMallocNode(Opcode o,PrimType typ,TyIdx typeIdx,BaseNode * opnd)483     JarrayMallocNode(Opcode o, PrimType typ, TyIdx typeIdx, BaseNode *opnd) : UnaryNode(o, typ, opnd), tyIdx(typeIdx) {}
484 
485     virtual ~JarrayMallocNode() = default;
486 
487     void Dump(int32 indent) const override;
488 
CloneTree(MapleAllocator & allocator)489     JarrayMallocNode *CloneTree(MapleAllocator &allocator) const override
490     {
491         auto *node = allocator.GetMemPool()->New<JarrayMallocNode>(*this);
492         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
493         return node;
494     }
495 
GetTyIdx()496     TyIdx GetTyIdx() const
497     {
498         return tyIdx;
499     }
500 
SetTyIdx(TyIdx idx)501     void SetTyIdx(TyIdx idx)
502     {
503         tyIdx = idx;
504     }
505 
506 private:
507     TyIdx tyIdx = TyIdx(0);
508 };
509 
510 // iaddrof also use this node
511 class IreadNode : public UnaryNode {
512 public:
IreadNode(Opcode o)513     explicit IreadNode(Opcode o) : UnaryNode(o) {}
514 
IreadNode(Opcode o,PrimType typ)515     IreadNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
516 
IreadNode(Opcode o,PrimType typ,TyIdx typeIdx,FieldID fid)517     IreadNode(Opcode o, PrimType typ, TyIdx typeIdx, FieldID fid) : UnaryNode(o, typ), tyIdx(typeIdx), fieldID(fid) {}
518 
IreadNode(Opcode o,PrimType typ,TyIdx typeIdx,FieldID fid,BaseNode * expr)519     IreadNode(Opcode o, PrimType typ, TyIdx typeIdx, FieldID fid, BaseNode *expr)
520         : UnaryNode(o, typ, expr), tyIdx(typeIdx), fieldID(fid)
521     {
522     }
523 
524     virtual ~IreadNode() = default;
525     void Dump(int32 indent) const override;
526     bool Verify() const override;
527 
CloneTree(MapleAllocator & allocator)528     IreadNode *CloneTree(MapleAllocator &allocator) const override
529     {
530         auto *node = allocator.GetMemPool()->New<IreadNode>(*this);
531         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
532         return node;
533     }
534 
GetTyIdx()535     const TyIdx &GetTyIdx() const
536     {
537         return tyIdx;
538     }
539 
SetTyIdx(const TyIdx tyIdxVal)540     void SetTyIdx(const TyIdx tyIdxVal)
541     {
542         tyIdx = tyIdxVal;
543     }
544 
GetFieldID()545     FieldID GetFieldID() const
546     {
547         return fieldID;
548     }
549 
SetFieldID(FieldID fieldIDVal)550     void SetFieldID(FieldID fieldIDVal)
551     {
552         fieldID = fieldIDVal;
553     }
554 
555     bool IsSameContent(const BaseNode *node) const override;
556 
557     // the base of an address expr is either a leaf or an iread
GetAddrExprBase()558     BaseNode &GetAddrExprBase() const
559     {
560         BaseNode *base = Opnd(0);
561         while (base->NumOpnds() != 0 && base->GetOpCode() != OP_iread) {
562             base = base->Opnd(0);
563         }
564         return *base;
565     }
566 
567     bool IsVolatile() const;
568 
569     MIRType *GetType() const;
570 
571 protected:
572     TyIdx tyIdx = TyIdx(0);
573     FieldID fieldID = 0;
574 };
575 
576 // IaddrofNode has the same member fields and member methods as IreadNode
577 using IaddrofNode = IreadNode;
578 
579 class IreadoffNode : public UnaryNode {
580 public:
IreadoffNode()581     IreadoffNode() : UnaryNode(OP_ireadoff) {}
582 
IreadoffNode(PrimType ptyp,int32 ofst)583     IreadoffNode(PrimType ptyp, int32 ofst) : UnaryNode(OP_ireadoff, ptyp), offset(ofst) {}
584 
IreadoffNode(PrimType ptyp,BaseNode * opnd,int32 ofst)585     IreadoffNode(PrimType ptyp, BaseNode *opnd, int32 ofst) : UnaryNode(OP_ireadoff, ptyp, opnd), offset(ofst) {}
586 
587     virtual ~IreadoffNode() = default;
588 
589     void Dump(int32 indent) const override;
590     bool Verify() const override;
591 
CloneTree(MapleAllocator & allocator)592     IreadoffNode *CloneTree(MapleAllocator &allocator) const override
593     {
594         auto *node = allocator.GetMemPool()->New<IreadoffNode>(*this);
595         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
596         return node;
597     }
598 
GetOffset()599     int32 GetOffset() const
600     {
601         return offset;
602     }
603 
SetOffset(int32 offsetValue)604     void SetOffset(int32 offsetValue)
605     {
606         offset = offsetValue;
607     }
608 
609     bool IsSameContent(const BaseNode *node) const override;
610 
611 private:
612     int32 offset = 0;
613 };
614 
615 class IreadFPoffNode : public BaseNode {
616 public:
IreadFPoffNode()617     IreadFPoffNode() : BaseNode(OP_ireadfpoff) {}
618 
IreadFPoffNode(PrimType ptyp,int32 ofst)619     IreadFPoffNode(PrimType ptyp, int32 ofst) : BaseNode(OP_ireadfpoff, ptyp, 0), offset(ofst) {}
620 
621     virtual ~IreadFPoffNode() = default;
622 
623     void Dump(int32 indent) const override;
624     bool Verify() const override;
625 
CloneTree(MapleAllocator & allocator)626     IreadFPoffNode *CloneTree(MapleAllocator &allocator) const override
627     {
628         auto *node = allocator.GetMemPool()->New<IreadFPoffNode>(*this);
629         return node;
630     }
631 
GetOffset()632     int32 GetOffset() const
633     {
634         return offset;
635     }
636 
SetOffset(int32 offsetValue)637     void SetOffset(int32 offsetValue)
638     {
639         offset = offsetValue;
640     }
641 
642     bool IsSameContent(const BaseNode *node) const override;
643 
644 private:
645     int32 offset = 0;
646 };
647 
648 class IreadPCoffNode : public IreadFPoffNode {
649 public:
IreadPCoffNode(Opcode o,PrimType typ,uint8 numopns)650     IreadPCoffNode(Opcode o, PrimType typ, uint8 numopns)
651     {
652         op = o;
653         ptyp = typ;
654         numOpnds = numopns;
655     }
~IreadPCoffNode()656     virtual ~IreadPCoffNode() {}
657 };
658 
659 typedef IreadPCoffNode AddroffPCNode;
660 
661 class BinaryOpnds {
662 public:
663     virtual ~BinaryOpnds() = default;
664 
665     virtual void Dump(int32 indent) const;
666 
GetBOpnd(size_t i)667     BaseNode *GetBOpnd(size_t i) const
668     {
669         CHECK_FATAL(i < kOperandNumBinary, "Invalid operand idx in BinaryOpnds");
670         return bOpnd[i];
671     }
672 
SetBOpnd(BaseNode * node,size_t i)673     void SetBOpnd(BaseNode *node, size_t i)
674     {
675         CHECK_FATAL(i < kOperandNumBinary, "Invalid operand idx in BinaryOpnds");
676         bOpnd[i] = node;
677     }
678 
679     virtual bool IsSameContent(const BaseNode *node) const;
680 
681 private:
682     BaseNode *bOpnd[kOperandNumBinary];
683 };
684 
685 class BinaryNode : public BaseNode, public BinaryOpnds {
686 public:
BinaryNode(Opcode o)687     explicit BinaryNode(Opcode o) : BaseNode(o, kOperandNumBinary) {}
688 
BinaryNode(Opcode o,PrimType typ)689     BinaryNode(Opcode o, PrimType typ) : BaseNode(o, typ, kOperandNumBinary) {}
690 
BinaryNode(Opcode o,PrimType typ,BaseNode * l,BaseNode * r)691     BinaryNode(Opcode o, PrimType typ, BaseNode *l, BaseNode *r) : BaseNode(o, typ, kOperandNumBinary)
692     {
693         SetBOpnd(l, 0);
694         SetBOpnd(r, 1);
695     }
696 
697     virtual ~BinaryNode() = default;
698 
699     using BaseNode::Dump;
700     void Dump(int32 indent) const override;
701     bool Verify() const override;
702 
CloneTree(MapleAllocator & allocator)703     BinaryNode *CloneTree(MapleAllocator &allocator) const override
704     {
705         auto *node = allocator.GetMemPool()->New<BinaryNode>(*this);
706         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
707         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
708         return node;
709     }
710 
IsCommutative()711     bool IsCommutative() const
712     {
713         switch (GetOpCode()) {
714             case OP_add:
715             case OP_mul:
716             case OP_band:
717             case OP_bior:
718             case OP_bxor:
719             case OP_land:
720             case OP_lior:
721                 return true;
722             default:
723                 return false;
724         }
725     }
726 
Opnd(size_t i)727     BaseNode *Opnd(size_t i) const override
728     {
729         DEBUG_ASSERT(i < kOperandNumBinary, "invalid operand idx in BinaryNode");
730         DEBUG_ASSERT(i >= 0, "invalid operand idx in BinaryNode");
731         return GetBOpnd(i);
732     }
733 
NumOpnds()734     size_t NumOpnds() const override
735     {
736         return kOperandNumBinary;
737     }
738 
739     void SetOpnd(BaseNode *node, size_t i = 0) override
740     {
741         SetBOpnd(node, i);
742     }
743 
IsLeaf()744     bool IsLeaf() const override
745     {
746         return false;
747     }
748 
IsBinaryNode()749     bool IsBinaryNode() const override
750     {
751         return true;
752     }
753     bool IsSameContent(const BaseNode *node) const override;
754 };
755 
756 class CompareNode : public BinaryNode {
757 public:
CompareNode(Opcode o)758     explicit CompareNode(Opcode o) : BinaryNode(o) {}
759 
CompareNode(Opcode o,PrimType typ)760     CompareNode(Opcode o, PrimType typ) : BinaryNode(o, typ) {}
761 
CompareNode(Opcode o,PrimType typ,PrimType otype,BaseNode * l,BaseNode * r)762     CompareNode(Opcode o, PrimType typ, PrimType otype, BaseNode *l, BaseNode *r)
763         : BinaryNode(o, typ, l, r), opndType(otype)
764     {
765     }
766 
767     virtual ~CompareNode() = default;
768 
769     using BinaryNode::Dump;
770     void Dump(int32 indent) const override;
771     bool Verify() const override;
772 
CloneTree(MapleAllocator & allocator)773     CompareNode *CloneTree(MapleAllocator &allocator) const override
774     {
775         auto *node = allocator.GetMemPool()->New<CompareNode>(*this);
776         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
777         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
778         return node;
779     }
780 
GetOpndType()781     PrimType GetOpndType() const
782     {
783         return opndType;
784     }
785 
SetOpndType(PrimType type)786     void SetOpndType(PrimType type)
787     {
788         opndType = type;
789     }
790 
791 private:
792     PrimType opndType = kPtyInvalid;  // type of operands.
793 };
794 
795 class DepositbitsNode : public BinaryNode {
796 public:
DepositbitsNode()797     DepositbitsNode() : BinaryNode(OP_depositbits) {}
798 
DepositbitsNode(Opcode o,PrimType typ)799     DepositbitsNode(Opcode o, PrimType typ) : BinaryNode(o, typ) {}
800 
DepositbitsNode(Opcode o,PrimType typ,uint8 offset,uint8 size,BaseNode * l,BaseNode * r)801     DepositbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size, BaseNode *l, BaseNode *r)
802         : BinaryNode(o, typ, l, r), bitsOffset(offset), bitsSize(size)
803     {
804     }
805 
806     virtual ~DepositbitsNode() = default;
807 
808     void Dump(int32 indent) const override;
809     bool Verify() const override;
810 
CloneTree(MapleAllocator & allocator)811     DepositbitsNode *CloneTree(MapleAllocator &allocator) const override
812     {
813         auto *node = allocator.GetMemPool()->New<DepositbitsNode>(*this);
814         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
815         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
816         return node;
817     }
818 
GetBitsOffset()819     uint8 GetBitsOffset() const
820     {
821         return bitsOffset;
822     }
823 
SetBitsOffset(uint8 offset)824     void SetBitsOffset(uint8 offset)
825     {
826         bitsOffset = offset;
827     }
828 
GetBitsSize()829     uint8 GetBitsSize() const
830     {
831         return bitsSize;
832     }
833 
SetBitsSize(uint8 size)834     void SetBitsSize(uint8 size)
835     {
836         bitsSize = size;
837     }
838 
839 private:
840     uint8 bitsOffset = 0;
841     uint8 bitsSize = 0;
842 };
843 
844 // used for resolveinterfacefunc, resolvevirtualfunc
845 // bOpnd[0] stores base vtab/itab address
846 // bOpnd[1] stores offset
847 class ResolveFuncNode : public BinaryNode {
848 public:
ResolveFuncNode(Opcode o)849     explicit ResolveFuncNode(Opcode o) : BinaryNode(o) {}
850 
ResolveFuncNode(Opcode o,PrimType typ)851     ResolveFuncNode(Opcode o, PrimType typ) : BinaryNode(o, typ) {}
852 
ResolveFuncNode(Opcode o,PrimType typ,PUIdx idx)853     ResolveFuncNode(Opcode o, PrimType typ, PUIdx idx) : BinaryNode(o, typ), puIdx(idx) {}
854 
ResolveFuncNode(Opcode o,PrimType typ,PUIdx pIdx,BaseNode * opnd0,BaseNode * opnd1)855     ResolveFuncNode(Opcode o, PrimType typ, PUIdx pIdx, BaseNode *opnd0, BaseNode *opnd1)
856         : BinaryNode(o, typ, opnd0, opnd1), puIdx(pIdx)
857     {
858     }
859 
860     virtual ~ResolveFuncNode() = default;
861 
862     void Dump(int32 indent) const override;
863 
CloneTree(MapleAllocator & allocator)864     ResolveFuncNode *CloneTree(MapleAllocator &allocator) const override
865     {
866         auto *node = allocator.GetMemPool()->New<ResolveFuncNode>(*this);
867         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
868         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
869         return node;
870     }
871 
GetTabBaseAddr()872     BaseNode *GetTabBaseAddr() const
873     {
874         return GetBOpnd(0);
875     }
876 
GetOffset()877     BaseNode *GetOffset() const
878     {
879         return GetBOpnd(1);
880     }
881 
GetPuIdx()882     PUIdx GetPuIdx() const
883     {
884         return puIdx;
885     }
886 
SetPUIdx(PUIdx idx)887     void SetPUIdx(PUIdx idx)
888     {
889         puIdx = idx;
890     }
891 
892 private:
893     PUIdx puIdx = 0;
894 };
895 
896 class TernaryNode : public BaseNode {
897 public:
TernaryNode(Opcode o)898     explicit TernaryNode(Opcode o) : BaseNode(o, kOperandNumTernary) {}
899 
TernaryNode(Opcode o,PrimType typ)900     TernaryNode(Opcode o, PrimType typ) : BaseNode(o, typ, kOperandNumTernary) {}
901 
TernaryNode(Opcode o,PrimType typ,BaseNode * e0,BaseNode * e1,BaseNode * e2)902     TernaryNode(Opcode o, PrimType typ, BaseNode *e0, BaseNode *e1, BaseNode *e2) : BaseNode(o, typ, kOperandNumTernary)
903     {
904         topnd[kFirstOpnd] = e0;
905         topnd[kSecondOpnd] = e1;
906         topnd[kThirdOpnd] = e2;
907     }
908 
909     virtual ~TernaryNode() = default;
910 
911     void Dump(int32 indent) const override;
912     bool Verify() const override;
913 
CloneTree(MapleAllocator & allocator)914     TernaryNode *CloneTree(MapleAllocator &allocator) const override
915     {
916         auto *node = allocator.GetMemPool()->New<TernaryNode>(*this);
917         node->topnd[kFirstOpnd] = topnd[kFirstOpnd]->CloneTree(allocator);
918         node->topnd[kSecondOpnd] = topnd[kSecondOpnd]->CloneTree(allocator);
919         node->topnd[kThirdOpnd] = topnd[kThirdOpnd]->CloneTree(allocator);
920         return node;
921     }
922 
Opnd(size_t i)923     BaseNode *Opnd(size_t i) const override
924     {
925         CHECK_FATAL(i < kOperandNumTernary, "array index out of range");
926         return topnd[i];
927     }
928 
NumOpnds()929     size_t NumOpnds() const override
930     {
931         return kOperandNumTernary;
932     }
933 
934     void SetOpnd(BaseNode *node, size_t i = 0) override
935     {
936         CHECK_FATAL(i < kOperandNumTernary, "array index out of range");
937         topnd[i] = node;
938     }
939 
IsLeaf()940     bool IsLeaf() const override
941     {
942         return false;
943     }
944 
IsTernaryNode()945     bool IsTernaryNode() const override
946     {
947         return true;
948     }
949 
950 private:
951     BaseNode *topnd[kOperandNumTernary] = {nullptr, nullptr, nullptr};
952 };
953 
954 class NaryOpnds {
955 public:
NaryOpnds(MapleAllocator & mpallocter)956     explicit NaryOpnds(MapleAllocator &mpallocter) : nOpnd(mpallocter.Adapter()) {}
957 
958     virtual ~NaryOpnds() = default;
959 
960     virtual void Dump(int32 indent) const;
961     bool VerifyOpnds() const;
962 
GetNopnd()963     const MapleVector<BaseNode *> &GetNopnd() const
964     {
965         return nOpnd;
966     }
967 
GetNopnd()968     MapleVector<BaseNode *> &GetNopnd()
969     {
970         return nOpnd;
971     }
972 
GetNopndSize()973     size_t GetNopndSize() const
974     {
975         return nOpnd.size();
976     }
977 
GetNopndAt(size_t i)978     BaseNode *GetNopndAt(size_t i) const
979     {
980         CHECK_FATAL(i < nOpnd.size(), "array index out of range");
981         return nOpnd[i];
982     }
983 
SetNOpndAt(size_t i,BaseNode * opnd)984     void SetNOpndAt(size_t i, BaseNode *opnd)
985     {
986         CHECK_FATAL(i < nOpnd.size(), "array index out of range");
987         nOpnd[i] = opnd;
988     }
989 
SetNOpnd(const MapleVector<BaseNode * > & val)990     void SetNOpnd(const MapleVector<BaseNode *> &val)
991     {
992         nOpnd = val;
993     }
994 
995 private:
996     MapleVector<BaseNode *> nOpnd;
997 };
998 
999 class MapleValue {
1000 public:
MapleValue(PregIdx preg)1001     MapleValue(PregIdx preg) : pregIdx(preg), kind(kPregKind) {}
MapleValue(MIRSymbol * sym)1002     MapleValue(MIRSymbol *sym) : symbol(sym), kind(kSymbolKind) {}
MapleValue(MIRConst * value)1003     MapleValue(MIRConst *value) : constVal(value), kind(kConstKind) {}
1004     MapleValue(const MapleValue &val) = default;
1005     ~MapleValue() = default;
1006 
1007     enum MapleValueKind {
1008         kPregKind,
1009         kSymbolKind,
1010         kConstKind,
1011     };
1012 
GetMapleValueKind()1013     MapleValueKind GetMapleValueKind() const
1014     {
1015         return kind;
1016     }
1017 
GetSymbol()1018     const MIRSymbol &GetSymbol() const
1019     {
1020         DEBUG_ASSERT(symbol != nullptr, "value is not be initialized with symbol");
1021         return *symbol;
1022     }
1023 
GetPregIdx()1024     PregIdx GetPregIdx() const
1025     {
1026         DEBUG_ASSERT(kind == kPregKind, "value is not be initialized with preg");
1027         return pregIdx;
1028     }
1029 
GetConstValue()1030     const MIRConst &GetConstValue() const
1031     {
1032         DEBUG_ASSERT(kind == kConstKind, "value is not be initialized with preg");
1033         return *constVal;
1034     }
1035 
1036 private:
1037     PregIdx pregIdx = 0;
1038     MIRSymbol *symbol = nullptr;
1039     MIRConst *constVal = nullptr;
1040     MapleValueKind kind;
1041 };
1042 
1043 class DeoptBundleInfo {
1044 public:
DeoptBundleInfo(MapleAllocator & mpallocter)1045     explicit DeoptBundleInfo(MapleAllocator &mpallocter) : deoptBundleInfo(mpallocter.Adapter()) {}
1046 
1047     virtual ~DeoptBundleInfo() = default;
1048 
1049     virtual void Dump(int32 indent) const;
1050 
GetDeoptBundleInfo()1051     const MapleUnorderedMap<int32, MapleValue> &GetDeoptBundleInfo() const
1052     {
1053         return deoptBundleInfo;
1054     }
1055 
GetDeoptBundleInfo()1056     MapleUnorderedMap<int32, MapleValue> &GetDeoptBundleInfo()
1057     {
1058         return deoptBundleInfo;
1059     }
1060 
SetDeoptBundleInfo(const MapleUnorderedMap<int32,MapleValue> & vregMap)1061     void SetDeoptBundleInfo(const MapleUnorderedMap<int32, MapleValue> &vregMap)
1062     {
1063         deoptBundleInfo = vregMap;
1064     }
1065 
AddDeoptBundleInfo(int32 deoptVreg,MapleValue value)1066     void AddDeoptBundleInfo(int32 deoptVreg, MapleValue value)
1067     {
1068         deoptBundleInfo.insert(std::pair<int32, MapleValue>(deoptVreg, value));
1069     }
1070 
1071 private:
1072     MapleUnorderedMap<int32, MapleValue> deoptBundleInfo;
1073 };
1074 
1075 class NaryNode : public BaseNode, public NaryOpnds {
1076 public:
NaryNode(MapleAllocator & allocator,Opcode o)1077     NaryNode(MapleAllocator &allocator, Opcode o) : BaseNode(o), NaryOpnds(allocator) {}
1078 
NaryNode(const MIRModule & mod,Opcode o)1079     NaryNode(const MIRModule &mod, Opcode o) : NaryNode(mod.GetCurFuncCodeMPAllocator(), o) {}
1080 
NaryNode(MapleAllocator & allocator,Opcode o,PrimType typ)1081     NaryNode(MapleAllocator &allocator, Opcode o, PrimType typ) : BaseNode(o, typ, 0), NaryOpnds(allocator) {}
1082 
NaryNode(const MIRModule & mod,Opcode o,PrimType typ)1083     NaryNode(const MIRModule &mod, Opcode o, PrimType typ) : NaryNode(mod.GetCurFuncCodeMPAllocator(), o, typ) {}
1084 
NaryNode(MapleAllocator & allocator,const NaryNode & node)1085     NaryNode(MapleAllocator &allocator, const NaryNode &node)
1086         : BaseNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds), NaryOpnds(allocator)
1087     {
1088     }
1089 
NaryNode(const MIRModule & mod,const NaryNode & node)1090     NaryNode(const MIRModule &mod, const NaryNode &node) : NaryNode(mod.GetCurFuncCodeMPAllocator(), node) {}
1091 
1092     NaryNode(NaryNode &node) = delete;
1093     NaryNode &operator=(const NaryNode &node) = delete;
1094     virtual ~NaryNode() = default;
1095 
1096     void Dump(int32 indent) const override;
1097 
CloneTree(MapleAllocator & allocator)1098     NaryNode *CloneTree(MapleAllocator &allocator) const override
1099     {
1100         auto *node = allocator.GetMemPool()->New<NaryNode>(allocator, *this);
1101         for (size_t i = 0; i < GetNopndSize(); ++i) {
1102             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
1103         }
1104         return node;
1105     }
1106 
Opnd(size_t i)1107     BaseNode *Opnd(size_t i) const override
1108     {
1109         return GetNopndAt(i);
1110     }
1111 
NumOpnds()1112     size_t NumOpnds() const override
1113     {
1114         DEBUG_ASSERT(numOpnds == GetNopndSize(), "NaryNode has wrong numOpnds field");
1115         return GetNopndSize();
1116     }
1117 
1118     void SetOpnd(BaseNode *node, size_t i = 0) override
1119     {
1120         DEBUG_ASSERT(i < GetNopnd().size(), "array index out of range");
1121         SetNOpndAt(i, node);
1122     }
1123 
IsLeaf()1124     bool IsLeaf() const override
1125     {
1126         return false;
1127     }
1128 
Verify()1129     bool Verify() const override
1130     {
1131         return true;
1132     }
1133 
IsNaryNode()1134     bool IsNaryNode() const override
1135     {
1136         return true;
1137     }
1138 };
1139 
1140 class IntrinsicopNode : public NaryNode {
1141 public:
1142     IntrinsicopNode(MapleAllocator &allocator, Opcode o, TyIdx typeIdx = TyIdx())
NaryNode(allocator,o)1143         : NaryNode(allocator, o), intrinsic(INTRN_UNDEFINED), tyIdx(typeIdx)
1144     {
1145     }
1146 
1147     IntrinsicopNode(const MIRModule &mod, Opcode o, TyIdx typeIdx = TyIdx())
1148         : IntrinsicopNode(mod.GetCurFuncCodeMPAllocator(), o, typeIdx)
1149     {
1150     }
1151 
1152     IntrinsicopNode(MapleAllocator &allocator, Opcode o, PrimType typ, TyIdx typeIdx = TyIdx())
NaryNode(allocator,o,typ)1153         : NaryNode(allocator, o, typ), intrinsic(INTRN_UNDEFINED), tyIdx(typeIdx)
1154     {
1155     }
1156 
1157     IntrinsicopNode(const MIRModule &mod, Opcode o, PrimType typ, TyIdx typeIdx = TyIdx())
1158         : IntrinsicopNode(mod.GetCurFuncCodeMPAllocator(), o, typ, typeIdx)
1159     {
1160     }
1161 
IntrinsicopNode(MapleAllocator & allocator,const IntrinsicopNode & node)1162     IntrinsicopNode(MapleAllocator &allocator, const IntrinsicopNode &node)
1163         : NaryNode(allocator, node), intrinsic(node.GetIntrinsic()), tyIdx(node.GetTyIdx())
1164     {
1165     }
1166 
IntrinsicopNode(const MIRModule & mod,const IntrinsicopNode & node)1167     IntrinsicopNode(const MIRModule &mod, const IntrinsicopNode &node)
1168         : IntrinsicopNode(mod.GetCurFuncCodeMPAllocator(), node)
1169     {
1170     }
1171 
1172     IntrinsicopNode(IntrinsicopNode &node) = delete;
1173     IntrinsicopNode &operator=(const IntrinsicopNode &node) = delete;
1174     virtual ~IntrinsicopNode() = default;
1175 
1176     void Dump(int32 indent) const override;
1177     bool Verify() const override;
1178     bool Verify(VerifyResult &verifyResult) const override;
1179 
CloneTree(MapleAllocator & allocator)1180     IntrinsicopNode *CloneTree(MapleAllocator &allocator) const override
1181     {
1182         auto *node = allocator.GetMemPool()->New<IntrinsicopNode>(allocator, *this);
1183         for (size_t i = 0; i < GetNopndSize(); ++i) {
1184             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
1185         }
1186         node->SetNumOpnds(GetNopndSize());
1187         return node;
1188     }
1189 
GetIntrinsic()1190     MIRIntrinsicID GetIntrinsic() const
1191     {
1192         return intrinsic;
1193     }
1194 
SetIntrinsic(MIRIntrinsicID intrinsicID)1195     void SetIntrinsic(MIRIntrinsicID intrinsicID)
1196     {
1197         intrinsic = intrinsicID;
1198     }
1199 
GetTyIdx()1200     TyIdx GetTyIdx() const
1201     {
1202         return tyIdx;
1203     }
1204 
SetTyIdx(TyIdx idx)1205     void SetTyIdx(TyIdx idx)
1206     {
1207         tyIdx = idx;
1208     }
1209 
1210     // IntrinDesc query
GetIntrinDesc()1211     const IntrinDesc &GetIntrinDesc() const
1212     {
1213         return IntrinDesc::intrinTable[intrinsic];
1214     }
1215 
1216     bool VerifyJArrayLength(VerifyResult &verifyResult) const;
1217 
1218 private:
1219     MIRIntrinsicID intrinsic;
1220     TyIdx tyIdx;
1221 };
1222 
1223 class ConstvalNode : public BaseNode {
1224 public:
ConstvalNode()1225     ConstvalNode() : BaseNode(OP_constval) {}
1226 
ConstvalNode(PrimType typ)1227     explicit ConstvalNode(PrimType typ) : BaseNode(OP_constval, typ, 0) {}
1228 
ConstvalNode(MIRConst * constv)1229     explicit ConstvalNode(MIRConst *constv) : BaseNode(OP_constval), constVal(constv) {}
1230 
ConstvalNode(PrimType typ,MIRConst * constv)1231     ConstvalNode(PrimType typ, MIRConst *constv) : BaseNode(OP_constval, typ, 0), constVal(constv) {}
1232     virtual ~ConstvalNode() = default;
1233     void Dump(int32 indent) const override;
1234 
CloneTree(MapleAllocator & allocator)1235     ConstvalNode *CloneTree(MapleAllocator &allocator) const override
1236     {
1237         return allocator.GetMemPool()->New<ConstvalNode>(*this);
1238     }
1239 
GetConstVal()1240     const MIRConst *GetConstVal() const
1241     {
1242         return constVal;
1243     }
1244 
GetConstVal()1245     MIRConst *GetConstVal()
1246     {
1247         return constVal;
1248     }
1249 
SetConstVal(MIRConst * val)1250     void SetConstVal(MIRConst *val)
1251     {
1252         constVal = val;
1253     }
1254 
1255     bool IsSameContent(const BaseNode *node) const override;
1256 
1257 private:
1258     MIRConst *constVal = nullptr;
1259 };
1260 
1261 class ConststrNode : public BaseNode {
1262 public:
ConststrNode()1263     ConststrNode() : BaseNode(OP_conststr) {}
1264 
ConststrNode(UStrIdx i)1265     explicit ConststrNode(UStrIdx i) : BaseNode(OP_conststr), strIdx(i) {}
1266 
ConststrNode(PrimType typ,UStrIdx i)1267     ConststrNode(PrimType typ, UStrIdx i) : BaseNode(OP_conststr, typ, 0), strIdx(i) {}
1268 
1269     virtual ~ConststrNode() = default;
1270 
1271     void Dump(int32 indent) const override;
1272     bool IsSameContent(const BaseNode *node) const override;
1273 
CloneTree(MapleAllocator & allocator)1274     ConststrNode *CloneTree(MapleAllocator &allocator) const override
1275     {
1276         return allocator.GetMemPool()->New<ConststrNode>(*this);
1277     }
1278 
GetStrIdx()1279     UStrIdx GetStrIdx() const
1280     {
1281         return strIdx;
1282     }
1283 
SetStrIdx(UStrIdx idx)1284     void SetStrIdx(UStrIdx idx)
1285     {
1286         strIdx = idx;
1287     }
1288 
1289 private:
1290     UStrIdx strIdx = UStrIdx(0);
1291 };
1292 
1293 class Conststr16Node : public BaseNode {
1294 public:
Conststr16Node()1295     Conststr16Node() : BaseNode(OP_conststr16) {}
1296 
Conststr16Node(U16StrIdx i)1297     explicit Conststr16Node(U16StrIdx i) : BaseNode(OP_conststr16), strIdx(i) {}
1298 
Conststr16Node(PrimType typ,U16StrIdx i)1299     Conststr16Node(PrimType typ, U16StrIdx i) : BaseNode(OP_conststr16, typ, 0), strIdx(i) {}
1300 
1301     virtual ~Conststr16Node() = default;
1302 
1303     void Dump(int32 indent) const override;
1304     bool IsSameContent(const BaseNode *node) const override;
1305 
CloneTree(MapleAllocator & allocator)1306     Conststr16Node *CloneTree(MapleAllocator &allocator) const override
1307     {
1308         return allocator.GetMemPool()->New<Conststr16Node>(*this);
1309     }
1310 
GetStrIdx()1311     U16StrIdx GetStrIdx() const
1312     {
1313         return strIdx;
1314     }
1315 
SetStrIdx(U16StrIdx idx)1316     void SetStrIdx(U16StrIdx idx)
1317     {
1318         strIdx = idx;
1319     }
1320 
1321 private:
1322     U16StrIdx strIdx = U16StrIdx(0);
1323 };
1324 
1325 class SizeoftypeNode : public BaseNode {
1326 public:
SizeoftypeNode()1327     SizeoftypeNode() : BaseNode(OP_sizeoftype) {}
1328 
SizeoftypeNode(TyIdx t)1329     explicit SizeoftypeNode(TyIdx t) : BaseNode(OP_sizeoftype), tyIdx(t) {}
1330 
SizeoftypeNode(PrimType type,TyIdx t)1331     SizeoftypeNode(PrimType type, TyIdx t) : BaseNode(OP_sizeoftype, type, 0), tyIdx(t) {}
1332 
1333     virtual ~SizeoftypeNode() = default;
1334 
1335     void Dump(int32 indent) const override;
1336     bool Verify() const override;
1337 
CloneTree(MapleAllocator & allocator)1338     SizeoftypeNode *CloneTree(MapleAllocator &allocator) const override
1339     {
1340         return allocator.GetMemPool()->New<SizeoftypeNode>(*this);
1341     }
1342 
GetTyIdx()1343     TyIdx GetTyIdx() const
1344     {
1345         return tyIdx;
1346     }
1347 
SetTyIdx(TyIdx idx)1348     void SetTyIdx(TyIdx idx)
1349     {
1350         tyIdx = idx;
1351     }
1352 
1353 private:
1354     TyIdx tyIdx = TyIdx(0);
1355 };
1356 
1357 class FieldsDistNode : public BaseNode {
1358 public:
FieldsDistNode()1359     FieldsDistNode() : BaseNode(OP_fieldsdist) {}
1360 
FieldsDistNode(TyIdx t,FieldID f1,FieldID f2)1361     FieldsDistNode(TyIdx t, FieldID f1, FieldID f2) : BaseNode(OP_fieldsdist), tyIdx(t), fieldID1(f1), fieldID2(f2) {}
1362 
FieldsDistNode(PrimType typ,TyIdx t,FieldID f1,FieldID f2)1363     FieldsDistNode(PrimType typ, TyIdx t, FieldID f1, FieldID f2)
1364         : BaseNode(OP_fieldsdist, typ, 0), tyIdx(t), fieldID1(f1), fieldID2(f2)
1365     {
1366     }
1367 
1368     virtual ~FieldsDistNode() = default;
1369 
1370     void Dump(int32 indent) const override;
1371 
CloneTree(MapleAllocator & allocator)1372     FieldsDistNode *CloneTree(MapleAllocator &allocator) const override
1373     {
1374         return allocator.GetMemPool()->New<FieldsDistNode>(*this);
1375     }
1376 
GetTyIdx()1377     TyIdx GetTyIdx() const
1378     {
1379         return tyIdx;
1380     }
1381 
SetTyIdx(TyIdx idx)1382     void SetTyIdx(TyIdx idx)
1383     {
1384         tyIdx = idx;
1385     }
1386 
GetFieldID1()1387     FieldID GetFieldID1() const
1388     {
1389         return fieldID1;
1390     }
1391 
SetFiledID1(FieldID id)1392     void SetFiledID1(FieldID id)
1393     {
1394         fieldID1 = id;
1395     }
1396 
GetFieldID2()1397     FieldID GetFieldID2() const
1398     {
1399         return fieldID2;
1400     }
1401 
SetFiledID2(FieldID id)1402     void SetFiledID2(FieldID id)
1403     {
1404         fieldID2 = id;
1405     }
1406 
1407 private:
1408     TyIdx tyIdx = TyIdx(0);
1409     FieldID fieldID1 = 0;
1410     FieldID fieldID2 = 0;
1411 };
1412 
1413 class ArrayNode : public NaryNode {
1414 public:
ArrayNode(MapleAllocator & allocator)1415     ArrayNode(MapleAllocator &allocator) : NaryNode(allocator, OP_array) {}
1416 
ArrayNode(const MIRModule & mod)1417     explicit ArrayNode(const MIRModule &mod) : ArrayNode(mod.GetCurFuncCodeMPAllocator()) {}
1418 
ArrayNode(MapleAllocator & allocator,PrimType typ,TyIdx idx)1419     ArrayNode(MapleAllocator &allocator, PrimType typ, TyIdx idx) : NaryNode(allocator, OP_array, typ), tyIdx(idx) {}
1420 
ArrayNode(const MIRModule & mod,PrimType typ,TyIdx idx)1421     ArrayNode(const MIRModule &mod, PrimType typ, TyIdx idx) : ArrayNode(mod.GetCurFuncCodeMPAllocator(), typ, idx) {}
1422 
ArrayNode(MapleAllocator & allocator,PrimType typ,TyIdx idx,bool bcheck)1423     ArrayNode(MapleAllocator &allocator, PrimType typ, TyIdx idx, bool bcheck)
1424         : NaryNode(allocator, OP_array, typ), tyIdx(idx), boundsCheck(bcheck)
1425     {
1426     }
1427 
ArrayNode(const MIRModule & mod,PrimType typ,TyIdx idx,bool bcheck)1428     ArrayNode(const MIRModule &mod, PrimType typ, TyIdx idx, bool bcheck)
1429         : ArrayNode(mod.GetCurFuncCodeMPAllocator(), typ, idx, bcheck)
1430     {
1431     }
1432 
ArrayNode(MapleAllocator & allocator,const ArrayNode & node)1433     ArrayNode(MapleAllocator &allocator, const ArrayNode &node)
1434         : NaryNode(allocator, node), tyIdx(node.tyIdx), boundsCheck(node.boundsCheck)
1435     {
1436     }
1437 
ArrayNode(const MIRModule & mod,const ArrayNode & node)1438     ArrayNode(const MIRModule &mod, const ArrayNode &node) : ArrayNode(mod.GetCurFuncCodeMPAllocator(), node) {}
1439 
1440     ArrayNode(ArrayNode &node) = delete;
1441     ArrayNode &operator=(const ArrayNode &node) = delete;
1442     virtual ~ArrayNode() = default;
1443 
1444     void Dump(int32 indent) const override;
1445     bool Verify() const override;
1446     bool IsSameBase(ArrayNode *);
1447 
NumOpnds()1448     size_t NumOpnds() const override
1449     {
1450         DEBUG_ASSERT(numOpnds == GetNopndSize(), "ArrayNode has wrong numOpnds field");
1451         return GetNopndSize();
1452     }
1453 
CloneTree(MapleAllocator & allocator)1454     ArrayNode *CloneTree(MapleAllocator &allocator) const override
1455     {
1456         auto *node = allocator.GetMemPool()->New<ArrayNode>(allocator, *this);
1457         for (size_t i = 0; i < GetNopndSize(); ++i) {
1458             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
1459         }
1460         node->boundsCheck = boundsCheck;
1461         node->SetNumOpnds(GetNopndSize());
1462         return node;
1463     }
1464 
1465     const MIRType *GetArrayType(const TypeTable &tt) const;
1466     MIRType *GetArrayType(const TypeTable &tt);
1467 
GetIndex(size_t i)1468     BaseNode *GetIndex(size_t i)
1469     {
1470         return Opnd(i + 1);
1471     }
1472 
1473     const BaseNode *GetDim(const MIRModule &mod, TypeTable &tt, int i) const;
1474     BaseNode *GetDim(const MIRModule &mod, TypeTable &tt, int i);
1475 
GetBase()1476     BaseNode *GetBase()
1477     {
1478         return Opnd(0);
1479     }
1480 
GetTyIdx()1481     TyIdx GetTyIdx() const
1482     {
1483         return tyIdx;
1484     }
1485 
SetTyIdx(TyIdx idx)1486     void SetTyIdx(TyIdx idx)
1487     {
1488         tyIdx = idx;
1489     }
1490 
GetBoundsCheck()1491     bool GetBoundsCheck() const
1492     {
1493         return boundsCheck;
1494     }
1495 
SetBoundsCheck(bool check)1496     void SetBoundsCheck(bool check)
1497     {
1498         boundsCheck = check;
1499     }
1500 
1501 private:
1502     TyIdx tyIdx;
1503     bool boundsCheck = true;
1504 };
1505 
1506 class AddrofNode : public BaseNode {
1507 public:
AddrofNode(Opcode o)1508     explicit AddrofNode(Opcode o) : BaseNode(o), stIdx() {}
1509 
AddrofNode(Opcode o,PrimType typ)1510     AddrofNode(Opcode o, PrimType typ) : AddrofNode(o, typ, StIdx(), 0) {}
1511 
AddrofNode(Opcode o,PrimType typ,StIdx sIdx,FieldID fid)1512     AddrofNode(Opcode o, PrimType typ, StIdx sIdx, FieldID fid) : BaseNode(o, typ, 0), stIdx(sIdx), fieldID(fid) {}
1513 
1514     virtual ~AddrofNode() = default;
1515 
1516     void Dump(int32 indent) const override;
1517     bool Verify() const override;
1518     bool CheckNode(const MIRModule &mod) const;
1519 
CloneTree(MapleAllocator & allocator)1520     AddrofNode *CloneTree(MapleAllocator &allocator) const override
1521     {
1522         return allocator.GetMemPool()->New<AddrofNode>(*this);
1523     }
1524 
GetStIdx()1525     StIdx GetStIdx() const
1526     {
1527         return stIdx;
1528     }
1529 
SetStIdx(StIdx idx)1530     void SetStIdx(StIdx idx)
1531     {
1532         stIdx = idx;
1533     }
1534 
SetStFullIdx(uint32 idx)1535     void SetStFullIdx(uint32 idx)
1536     {
1537         stIdx.SetFullIdx(idx);
1538     }
1539 
GetFieldID()1540     FieldID GetFieldID() const
1541     {
1542         return fieldID;
1543     }
1544 
SetFieldID(FieldID fieldIDVal)1545     void SetFieldID(FieldID fieldIDVal)
1546     {
1547         fieldID = fieldIDVal;
1548     }
1549 
1550     bool IsVolatile(const MIRModule &mod) const;
1551 
1552     bool IsSameContent(const BaseNode *node) const override;
1553 
1554 private:
1555     StIdx stIdx;
1556     FieldID fieldID = 0;
1557 };
1558 
1559 // DreadNode has the same member fields and member methods as AddrofNode
1560 using DreadNode = AddrofNode;
1561 
1562 class DreadoffNode : public BaseNode {
1563 public:
DreadoffNode(Opcode o)1564     explicit DreadoffNode(Opcode o) : BaseNode(o), stIdx() {}
1565 
DreadoffNode(Opcode o,PrimType typ)1566     DreadoffNode(Opcode o, PrimType typ) : BaseNode(o, typ, 0), stIdx() {}
1567 
1568     virtual ~DreadoffNode() = default;
1569 
1570     void Dump(int32 indent) const override;
1571 
CloneTree(MapleAllocator & allocator)1572     DreadoffNode *CloneTree(MapleAllocator &allocator) const override
1573     {
1574         return allocator.GetMemPool()->New<DreadoffNode>(*this);
1575     }
1576 
1577     bool IsVolatile(const MIRModule &mod) const;
1578 
1579     bool IsSameContent(const BaseNode *node) const override;
1580 
1581 public:
1582     StIdx stIdx;
1583     int32 offset = 0;
1584 };
1585 
1586 // AddrofoffNode has the same member fields and member methods as DreadoffNode
1587 using AddrofoffNode = DreadoffNode;
1588 
1589 class RegreadNode : public BaseNode {
1590 public:
RegreadNode()1591     RegreadNode() : BaseNode(OP_regread) {}
1592 
RegreadNode(PregIdx pIdx)1593     explicit RegreadNode(PregIdx pIdx) : BaseNode(OP_regread), regIdx(pIdx) {}
1594 
RegreadNode(PrimType primType,PregIdx pIdx)1595     RegreadNode(PrimType primType, PregIdx pIdx) : RegreadNode(pIdx)
1596     {
1597         ptyp = primType;
1598     }
1599 
1600     virtual ~RegreadNode() = default;
1601 
1602     void Dump(int32 indent) const override;
1603     bool Verify() const override;
1604 
CloneTree(MapleAllocator & allocator)1605     RegreadNode *CloneTree(MapleAllocator &allocator) const override
1606     {
1607         return allocator.GetMemPool()->New<RegreadNode>(*this);
1608     }
1609 
GetRegIdx()1610     PregIdx GetRegIdx() const
1611     {
1612         return regIdx;
1613     }
SetRegIdx(PregIdx reg)1614     void SetRegIdx(PregIdx reg)
1615     {
1616         regIdx = reg;
1617     }
1618 
1619     bool IsSameContent(const BaseNode *node) const override;
1620 
1621 private:
1622     PregIdx regIdx = 0;  // 32bit, negative if special register
1623 };
1624 
1625 class AddroffuncNode : public BaseNode {
1626 public:
AddroffuncNode()1627     AddroffuncNode() : BaseNode(OP_addroffunc) {}
1628 
AddroffuncNode(PrimType typ,PUIdx pIdx)1629     AddroffuncNode(PrimType typ, PUIdx pIdx) : BaseNode(OP_addroffunc, typ, 0), puIdx(pIdx) {}
1630 
1631     virtual ~AddroffuncNode() = default;
1632 
1633     void Dump(int32 indent) const override;
1634     bool Verify() const override;
1635 
CloneTree(MapleAllocator & allocator)1636     AddroffuncNode *CloneTree(MapleAllocator &allocator) const override
1637     {
1638         return allocator.GetMemPool()->New<AddroffuncNode>(*this);
1639     }
1640 
GetPUIdx()1641     PUIdx GetPUIdx() const
1642     {
1643         return puIdx;
1644     }
1645 
SetPUIdx(PUIdx puIdxValue)1646     void SetPUIdx(PUIdx puIdxValue)
1647     {
1648         puIdx = puIdxValue;
1649     }
1650 
1651     bool IsSameContent(const BaseNode *node) const override;
1652 
1653 private:
1654     PUIdx puIdx = 0;  // 32bit now
1655 };
1656 
1657 class AddroflabelNode : public BaseNode {
1658 public:
AddroflabelNode()1659     AddroflabelNode() : BaseNode(OP_addroflabel) {}
1660 
AddroflabelNode(uint32 ofst)1661     explicit AddroflabelNode(uint32 ofst) : BaseNode(OP_addroflabel), offset(ofst) {}
1662 
1663     virtual ~AddroflabelNode() = default;
1664 
1665     void Dump(int32 indent) const override;
1666     bool Verify() const override;
1667 
CloneTree(MapleAllocator & allocator)1668     AddroflabelNode *CloneTree(MapleAllocator &allocator) const override
1669     {
1670         return allocator.GetMemPool()->New<AddroflabelNode>(*this);
1671     }
1672 
GetOffset()1673     uint32 GetOffset() const
1674     {
1675         return offset;
1676     }
1677 
SetOffset(uint32 offsetValue)1678     void SetOffset(uint32 offsetValue)
1679     {
1680         offset = offsetValue;
1681     }
1682 
1683     bool IsSameContent(const BaseNode *node) const override;
1684 
1685 private:
1686     LabelIdx offset = 0;
1687 };
1688 
1689 // for cleanuptry, jscatch, finally, retsub, endtry, membaracquire, membarrelease,
1690 // membarstoreload, membarstorestore
1691 class StmtNode : public BaseNode, public PtrListNodeBase<StmtNode> {
1692 public:
1693     static std::atomic<uint32> stmtIDNext;  // for assigning stmtID, initialized to 1; 0 is reserved
1694     static uint32 lastPrintedLineNum;       // used during printing ascii output
1695     static uint16 lastPrintedColumnNum;
1696 
StmtNode(Opcode o)1697     explicit StmtNode(Opcode o) : BaseNode(o), PtrListNodeBase(), stmtID(stmtIDNext), stmtOriginalID(stmtIDNext)
1698     {
1699         ++stmtIDNext;
1700     }
1701 
StmtNode(Opcode o,uint8 numOpr)1702     StmtNode(Opcode o, uint8 numOpr)
1703         : BaseNode(o, numOpr), PtrListNodeBase(), stmtID(stmtIDNext), stmtOriginalID(stmtIDNext)
1704     {
1705         ++stmtIDNext;
1706     }
1707 
StmtNode(Opcode o,PrimType typ,uint8 numOpr)1708     StmtNode(Opcode o, PrimType typ, uint8 numOpr)
1709         : BaseNode(o, typ, numOpr), PtrListNodeBase(), stmtID(stmtIDNext), stmtOriginalID(stmtIDNext)
1710     {
1711         ++stmtIDNext;
1712     }
1713 
1714     // used for NaryStmtNode when clone
StmtNode(Opcode o,PrimType typ,uint8 numOpr,const SrcPosition & srcPosition,uint32 stmtOriginalID,StmtAttrs attrs)1715     StmtNode(Opcode o, PrimType typ, uint8 numOpr, const SrcPosition &srcPosition, uint32 stmtOriginalID,
1716              StmtAttrs attrs)
1717         : BaseNode(o, typ, numOpr),
1718           PtrListNodeBase(),
1719           srcPosition(srcPosition),
1720           stmtID(stmtIDNext),
1721           stmtOriginalID(stmtOriginalID),
1722           stmtAttrs(attrs)
1723     {
1724         ++stmtIDNext;
1725     }
1726 
1727     virtual ~StmtNode() = default;
1728 
1729     using BaseNode::Dump;
1730     void DumpBase(int32 indent) const override;
1731     void Dump(int32 indent) const override;
1732     void InsertAfterThis(StmtNode &pos);
1733     void InsertBeforeThis(StmtNode &pos);
1734 
CloneTree(MapleAllocator & allocator)1735     virtual StmtNode *CloneTree(MapleAllocator &allocator) const override
1736     {
1737         auto *s = allocator.GetMemPool()->New<StmtNode>(*this);
1738         s->SetStmtID(stmtIDNext++);
1739         s->SetMeStmtID(meStmtID);
1740         return s;
1741     }
1742 
Verify()1743     virtual bool Verify() const override
1744     {
1745         return true;
1746     }
1747 
Verify(VerifyResult &)1748     virtual bool Verify(VerifyResult &) const override
1749     {
1750         return Verify();
1751     }
1752 
GetSrcPos()1753     const SrcPosition &GetSrcPos() const
1754     {
1755         return srcPosition;
1756     }
1757 
GetSrcPos()1758     SrcPosition &GetSrcPos()
1759     {
1760         return srcPosition;
1761     }
1762 
SetSrcPos(SrcPosition pos)1763     void SetSrcPos(SrcPosition pos)
1764     {
1765         srcPosition = pos;
1766     }
1767 
GetStmtID()1768     uint32 GetStmtID() const
1769     {
1770         return stmtID;
1771     }
1772 
SetStmtID(uint32 id)1773     void SetStmtID(uint32 id)
1774     {
1775         stmtID = id;
1776     }
1777 
GetOriginalID()1778     uint32 GetOriginalID() const
1779     {
1780         return stmtOriginalID;
1781     }
1782 
SetOriginalID(uint32 id)1783     void SetOriginalID(uint32 id)
1784     {
1785         stmtOriginalID = id;
1786     }
1787 
GetMeStmtID()1788     uint32 GetMeStmtID() const
1789     {
1790         return meStmtID;
1791     }
1792 
SetMeStmtID(uint32 id)1793     void SetMeStmtID(uint32 id)
1794     {
1795         meStmtID = id;
1796     }
1797 
1798     StmtNode *GetRealNext() const;
1799 
GetRHS()1800     virtual BaseNode *GetRHS() const
1801     {
1802         return nullptr;
1803     }
1804 
GetIsLive()1805     bool GetIsLive() const
1806     {
1807         return isLive;
1808     }
1809 
SetIsLive(bool live)1810     void SetIsLive(bool live) const
1811     {
1812         isLive = live;
1813     }
1814 
IsInSafeRegion()1815     bool IsInSafeRegion() const
1816     {
1817         return stmtAttrs.GetAttr(STMTATTR_insaferegion);
1818     }
1819 
SetInSafeRegion()1820     void SetInSafeRegion()
1821     {
1822         stmtAttrs.SetAttr(STMTATTR_insaferegion);
1823     }
1824 
CopySafeRegionAttr(const StmtAttrs & stmtAttr)1825     void CopySafeRegionAttr(const StmtAttrs &stmtAttr)
1826     {
1827         this->stmtAttrs.AppendAttr(stmtAttr.GetTargetAttrFlag(STMTATTR_insaferegion));
1828     }
1829 
GetStmtAttrs()1830     const StmtAttrs &GetStmtAttrs() const
1831     {
1832         return stmtAttrs;
1833     }
1834 
SetAttr(StmtAttrKind x)1835     void SetAttr(StmtAttrKind x)
1836     {
1837         stmtAttrs.SetAttr(x);
1838     }
1839 
GetAttr(StmtAttrKind x)1840     bool GetAttr(StmtAttrKind x) const
1841     {
1842         return stmtAttrs.GetAttr(x);
1843     }
1844 
SetStmtAttrs(StmtAttrs stmtAttrs_)1845     void SetStmtAttrs(StmtAttrs stmtAttrs_)
1846     {
1847         stmtAttrs = stmtAttrs_;
1848     }
1849 
1850 protected:
1851     SrcPosition srcPosition;
1852 
1853 private:
1854     uint32 stmtID;                // a unique ID assigned to it
1855     uint32 stmtOriginalID;        // first define id, no change when clone, need copy when emit from MeStmt
1856     uint32 meStmtID = 0;          // Need copy when emit from MeStmt, attention:this just for two stmt(if && call)
1857     mutable bool isLive = false;  // only used for dse to save compile time
1858                                   // mutable to keep const-ness at most situation
1859     StmtAttrs stmtAttrs;
1860 };
1861 
1862 class IassignNode : public StmtNode {
1863 public:
IassignNode()1864     IassignNode() : IassignNode(TyIdx(0), 0, nullptr, nullptr) {}
1865 
IassignNode(TyIdx tyIdx,FieldID fieldID,BaseNode * addrOpnd,BaseNode * rhsOpnd)1866     IassignNode(TyIdx tyIdx, FieldID fieldID, BaseNode *addrOpnd, BaseNode *rhsOpnd)
1867         : StmtNode(OP_iassign), tyIdx(tyIdx), fieldID(fieldID), addrExpr(addrOpnd), rhs(rhsOpnd)
1868     {
1869         BaseNodeT::SetNumOpnds(kOperandNumBinary);
1870     }
1871 
1872     virtual ~IassignNode() = default;
1873 
GetTyIdx()1874     TyIdx GetTyIdx() const
1875     {
1876         return tyIdx;
1877     }
1878 
SetTyIdx(TyIdx idx)1879     void SetTyIdx(TyIdx idx)
1880     {
1881         tyIdx = idx;
1882     }
1883 
GetFieldID()1884     FieldID GetFieldID() const
1885     {
1886         return fieldID;
1887     }
1888 
SetFieldID(FieldID fid)1889     void SetFieldID(FieldID fid)
1890     {
1891         fieldID = fid;
1892     }
1893 
Opnd(size_t i)1894     BaseNode *Opnd(size_t i) const override
1895     {
1896         if (i == 0) {
1897             return addrExpr;
1898         }
1899         return rhs;
1900     }
1901 
NumOpnds()1902     size_t NumOpnds() const override
1903     {
1904         return kOperandNumBinary;
1905     }
1906 
SetOpnd(BaseNode * node,size_t i)1907     void SetOpnd(BaseNode *node, size_t i) override
1908     {
1909         if (i == 0) {
1910             addrExpr = node;
1911         } else {
1912             rhs = node;
1913         }
1914     }
1915 
1916     void Dump(int32 indent) const override;
1917     bool Verify() const override;
1918 
CloneTree(MapleAllocator & allocator)1919     IassignNode *CloneTree(MapleAllocator &allocator) const override
1920     {
1921         auto *bn = allocator.GetMemPool()->New<IassignNode>(*this);
1922         bn->SetStmtID(stmtIDNext++);
1923         bn->SetOpnd(addrExpr->CloneTree(allocator), 0);
1924         bn->SetRHS(rhs->CloneTree(allocator));
1925         return bn;
1926     }
1927 
1928     // the base of an address expr is either a leaf or an iread
GetAddrExprBase()1929     BaseNode &GetAddrExprBase() const
1930     {
1931         BaseNode *base = addrExpr;
1932         while (base->NumOpnds() != 0 && base->GetOpCode() != OP_iread) {
1933             base = base->Opnd(0);
1934         }
1935         return *base;
1936     }
1937 
SetAddrExpr(BaseNode * exp)1938     void SetAddrExpr(BaseNode *exp)
1939     {
1940         addrExpr = exp;
1941     }
1942 
GetRHS()1943     BaseNode *GetRHS() const override
1944     {
1945         return rhs;
1946     }
1947 
SetRHS(BaseNode * node)1948     void SetRHS(BaseNode *node)
1949     {
1950         rhs = node;
1951     }
1952 
1953     bool AssigningVolatile() const;
1954 
1955 private:
1956     TyIdx tyIdx;
1957     FieldID fieldID;
1958 
1959 public:
1960     BaseNode *addrExpr;
1961     BaseNode *rhs;
1962 };
1963 
1964 // goto and gosub
1965 class GotoNode : public StmtNode {
1966 public:
GotoNode(Opcode o)1967     explicit GotoNode(Opcode o) : StmtNode(o) {}
1968 
GotoNode(Opcode o,uint32 ofst)1969     GotoNode(Opcode o, uint32 ofst) : StmtNode(o), offset(ofst) {}
1970 
1971     virtual ~GotoNode() = default;
1972 
1973     void Dump(int32 indent) const override;
1974 
CloneTree(MapleAllocator & allocator)1975     GotoNode *CloneTree(MapleAllocator &allocator) const override
1976     {
1977         auto *g = allocator.GetMemPool()->New<GotoNode>(*this);
1978         g->SetStmtID(stmtIDNext++);
1979         return g;
1980     }
1981 
GetOffset()1982     uint32 GetOffset() const
1983     {
1984         return offset;
1985     }
1986 
SetOffset(uint32 o)1987     void SetOffset(uint32 o)
1988     {
1989         offset = o;
1990     }
1991 
1992 private:
1993     uint32 offset = 0;
1994 };
1995 
1996 // jstry
1997 class JsTryNode : public StmtNode {
1998 public:
JsTryNode()1999     JsTryNode() : StmtNode(OP_jstry) {}
2000 
JsTryNode(uint16 catchofst,uint16 finallyofset)2001     JsTryNode(uint16 catchofst, uint16 finallyofset)
2002         : StmtNode(OP_jstry), catchOffset(catchofst), finallyOffset(finallyofset)
2003     {
2004     }
2005 
2006     virtual ~JsTryNode() = default;
2007 
2008     void Dump(int32 indent) const override;
2009 
CloneTree(MapleAllocator & allocator)2010     JsTryNode *CloneTree(MapleAllocator &allocator) const override
2011     {
2012         auto *t = allocator.GetMemPool()->New<JsTryNode>(*this);
2013         t->SetStmtID(stmtIDNext++);
2014         return t;
2015     }
2016 
GetCatchOffset()2017     uint16 GetCatchOffset() const
2018     {
2019         return catchOffset;
2020     }
2021 
SetCatchOffset(uint32 offset)2022     void SetCatchOffset(uint32 offset)
2023     {
2024         catchOffset = offset;
2025     }
2026 
GetFinallyOffset()2027     uint16 GetFinallyOffset() const
2028     {
2029         return finallyOffset;
2030     }
2031 
SetFinallyOffset(uint32 offset)2032     void SetFinallyOffset(uint32 offset)
2033     {
2034         finallyOffset = offset;
2035     }
2036 
2037 private:
2038     uint16 catchOffset = 0;
2039     uint16 finallyOffset = 0;
2040 };
2041 
2042 // try, cpptry
2043 class TryNode : public StmtNode {
2044 public:
TryNode(MapleAllocator & allocator)2045     explicit TryNode(MapleAllocator &allocator) : StmtNode(OP_try), offsets(allocator.Adapter()) {}
2046 
TryNode(const MapleVector<LabelIdx> & offsets)2047     explicit TryNode(const MapleVector<LabelIdx> &offsets) : StmtNode(OP_try), offsets(offsets) {}
2048 
TryNode(const MIRModule & mod)2049     explicit TryNode(const MIRModule &mod) : TryNode(mod.GetCurFuncCodeMPAllocator()) {}
2050 
2051     TryNode(TryNode &node) = delete;
2052     TryNode &operator=(const TryNode &node) = delete;
2053     virtual ~TryNode() = default;
2054 
2055     using StmtNode::Dump;
2056     void Dump(int32 indent) const override;
2057 
GetOffsets()2058     MapleVector<LabelIdx> &GetOffsets()
2059     {
2060         return offsets;
2061     }
2062 
GetOffset(size_t i)2063     LabelIdx GetOffset(size_t i) const
2064     {
2065         DEBUG_ASSERT(i < offsets.size(), "array index out of range");
2066         return offsets.at(i);
2067     }
2068 
SetOffset(LabelIdx offsetValue,size_t i)2069     void SetOffset(LabelIdx offsetValue, size_t i)
2070     {
2071         DEBUG_ASSERT(i < offsets.size(), "array index out of range");
2072         offsets[i] = offsetValue;
2073     }
2074 
AddOffset(LabelIdx offsetValue)2075     void AddOffset(LabelIdx offsetValue)
2076     {
2077         offsets.push_back(offsetValue);
2078     }
2079 
ResizeOffsets(size_t offsetSize)2080     void ResizeOffsets(size_t offsetSize)
2081     {
2082         offsets.resize(offsetSize);
2083     }
2084 
SetOffsets(const MapleVector<LabelIdx> & offsetsValue)2085     void SetOffsets(const MapleVector<LabelIdx> &offsetsValue)
2086     {
2087         offsets = offsetsValue;
2088     }
2089 
GetOffsetsCount()2090     size_t GetOffsetsCount() const
2091     {
2092         return offsets.size();
2093     }
2094 
GetOffsetsBegin()2095     MapleVector<LabelIdx>::iterator GetOffsetsBegin()
2096     {
2097         return offsets.begin();
2098     }
2099 
GetOffsetsEnd()2100     MapleVector<LabelIdx>::iterator GetOffsetsEnd()
2101     {
2102         return offsets.end();
2103     }
2104 
OffsetsInsert(MapleVector<LabelIdx>::iterator a,MapleVector<LabelIdx>::iterator b,MapleVector<LabelIdx>::iterator c)2105     void OffsetsInsert(MapleVector<LabelIdx>::iterator a, MapleVector<LabelIdx>::iterator b,
2106                        MapleVector<LabelIdx>::iterator c)
2107     {
2108         (void)offsets.insert(a, b, c);
2109     }
2110 
CloneTree(MapleAllocator & allocator)2111     TryNode *CloneTree(MapleAllocator &allocator) const override
2112     {
2113         auto *node = allocator.GetMemPool()->New<TryNode>(allocator);
2114         node->SetStmtID(stmtIDNext++);
2115         for (size_t i = 0; i < offsets.size(); ++i) {
2116             node->AddOffset(offsets[i]);
2117         }
2118         return node;
2119     }
2120 
2121 private:
2122     MapleVector<LabelIdx> offsets;
2123 };
2124 
2125 // catch
2126 class CatchNode : public StmtNode {
2127 public:
CatchNode(MapleAllocator & allocator)2128     explicit CatchNode(MapleAllocator &allocator) : StmtNode(OP_catch), exceptionTyIdxVec(allocator.Adapter()) {}
2129 
CatchNode(const MapleVector<TyIdx> & tyIdxVec)2130     explicit CatchNode(const MapleVector<TyIdx> &tyIdxVec) : StmtNode(OP_catch), exceptionTyIdxVec(tyIdxVec) {}
2131 
CatchNode(const MIRModule & mod)2132     explicit CatchNode(const MIRModule &mod) : CatchNode(mod.GetCurFuncCodeMPAllocator()) {}
2133 
2134     CatchNode(CatchNode &node) = delete;
2135     CatchNode &operator=(const CatchNode &node) = delete;
2136     virtual ~CatchNode() = default;
2137 
2138     using StmtNode::Dump;
2139     void Dump(int32 indent) const override;
2140 
GetExceptionTyIdxVecElement(size_t i)2141     TyIdx GetExceptionTyIdxVecElement(size_t i) const
2142     {
2143         CHECK_FATAL(i < exceptionTyIdxVec.size(), "array index out of range");
2144         return exceptionTyIdxVec[i];
2145     }
2146 
GetExceptionTyIdxVec()2147     const MapleVector<TyIdx> &GetExceptionTyIdxVec() const
2148     {
2149         return exceptionTyIdxVec;
2150     }
2151 
Size()2152     size_t Size() const
2153     {
2154         return exceptionTyIdxVec.size();
2155     }
2156 
SetExceptionTyIdxVecElement(TyIdx idx,size_t i)2157     void SetExceptionTyIdxVecElement(TyIdx idx, size_t i)
2158     {
2159         CHECK_FATAL(i < exceptionTyIdxVec.size(), "array index out of range");
2160         exceptionTyIdxVec[i] = idx;
2161     }
2162 
SetExceptionTyIdxVec(MapleVector<TyIdx> vec)2163     void SetExceptionTyIdxVec(MapleVector<TyIdx> vec)
2164     {
2165         exceptionTyIdxVec = vec;
2166     }
2167 
PushBack(TyIdx idx)2168     void PushBack(TyIdx idx)
2169     {
2170         exceptionTyIdxVec.push_back(idx);
2171     }
2172 
CloneTree(MapleAllocator & allocator)2173     CatchNode *CloneTree(MapleAllocator &allocator) const override
2174     {
2175         auto *node = allocator.GetMemPool()->New<CatchNode>(allocator);
2176         node->SetStmtID(stmtIDNext++);
2177         for (size_t i = 0; i < Size(); ++i) {
2178             node->PushBack(GetExceptionTyIdxVecElement(i));
2179         }
2180         return node;
2181     }
2182 
2183 private:
2184     MapleVector<TyIdx> exceptionTyIdxVec;
2185 };
2186 
2187 // cppcatch
2188 class CppCatchNode : public StmtNode {
2189 public:
CppCatchNode(const TyIdx & idx)2190     explicit CppCatchNode(const TyIdx &idx) : StmtNode(OP_cppcatch), exceptionTyIdx(idx) {}
CppCatchNode()2191     explicit CppCatchNode() : CppCatchNode(TyIdx(0)) {}
2192 
2193     explicit CppCatchNode(const CppCatchNode &node) = delete;
2194     CppCatchNode &operator=(const CppCatchNode &node) = delete;
2195     ~CppCatchNode() = default;
2196 
2197     void Dump(int32 indent) const override;
2198 
CloneTree(MapleAllocator & allocator)2199     CppCatchNode *CloneTree(MapleAllocator &allocator) const override
2200     {
2201         CppCatchNode *node = allocator.GetMemPool()->New<CppCatchNode>();
2202         node->SetStmtID(stmtIDNext++);
2203         node->exceptionTyIdx = exceptionTyIdx;
2204         return node;
2205     }
2206 
CloneTree(const MIRModule & mod)2207     CppCatchNode *CloneTree(const MIRModule &mod) const
2208     {
2209         return CppCatchNode::CloneTree(*mod.CurFuncCodeMemPoolAllocator());
2210     }
2211 
2212 public:
2213     TyIdx exceptionTyIdx;
2214 };
2215 
2216 using CasePair = std::pair<int64, LabelIdx>;
2217 using CaseVector = MapleVector<CasePair>;
2218 class SwitchNode : public StmtNode {
2219 public:
SwitchNode(MapleAllocator & allocator)2220     explicit SwitchNode(MapleAllocator &allocator) : StmtNode(OP_switch, 1), switchTable(allocator.Adapter()) {}
2221 
SwitchNode(const MIRModule & mod)2222     explicit SwitchNode(const MIRModule &mod) : SwitchNode(mod.GetCurFuncCodeMPAllocator()) {}
2223 
SwitchNode(MapleAllocator & allocator,LabelIdx label)2224     SwitchNode(MapleAllocator &allocator, LabelIdx label) : SwitchNode(allocator, label, nullptr) {}
2225 
SwitchNode(MapleAllocator & allocator,LabelIdx label,BaseNode * opnd)2226     SwitchNode(MapleAllocator &allocator, LabelIdx label, BaseNode *opnd)
2227         : StmtNode(OP_switch, 1), switchOpnd(opnd), defaultLabel(label), switchTable(allocator.Adapter())
2228     {
2229     }
2230 
SwitchNode(const MIRModule & mod,LabelIdx label)2231     SwitchNode(const MIRModule &mod, LabelIdx label) : SwitchNode(mod.GetCurFuncCodeMPAllocator(), label) {}
2232 
SwitchNode(MapleAllocator & allocator,const SwitchNode & node)2233     SwitchNode(MapleAllocator &allocator, const SwitchNode &node)
2234         : StmtNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds),
2235           defaultLabel(node.GetDefaultLabel()),
2236           switchTable(allocator.Adapter())
2237     {
2238     }
2239 
SwitchNode(const MIRModule & mod,const SwitchNode & node)2240     SwitchNode(const MIRModule &mod, const SwitchNode &node) : SwitchNode(mod.GetCurFuncCodeMPAllocator(), node) {}
2241 
2242     SwitchNode(SwitchNode &node) = delete;
2243     SwitchNode &operator=(const SwitchNode &node) = delete;
2244     virtual ~SwitchNode() = default;
2245 
2246     void Dump(int32 indent) const override;
2247     bool Verify() const override;
2248 
CloneTree(MapleAllocator & allocator)2249     SwitchNode *CloneTree(MapleAllocator &allocator) const override
2250     {
2251         auto *node = allocator.GetMemPool()->New<SwitchNode>(allocator, *this);
2252         node->SetSwitchOpnd(switchOpnd->CloneTree(allocator));
2253         for (size_t i = 0; i < switchTable.size(); ++i) {
2254             node->InsertCasePair(switchTable[i]);
2255         }
2256         return node;
2257     }
2258 
Opnd(size_t)2259     BaseNode *Opnd(size_t) const override
2260     {
2261         return switchOpnd;
2262     }
2263 
SetOpnd(BaseNode * node,size_t)2264     void SetOpnd(BaseNode *node, size_t) override
2265     {
2266         switchOpnd = node;
2267     }
2268 
GetSwitchOpnd()2269     BaseNode *GetSwitchOpnd() const
2270     {
2271         return switchOpnd;
2272     }
2273 
SetSwitchOpnd(BaseNode * node)2274     void SetSwitchOpnd(BaseNode *node)
2275     {
2276         switchOpnd = node;
2277     }
2278 
GetDefaultLabel()2279     LabelIdx GetDefaultLabel() const
2280     {
2281         return defaultLabel;
2282     }
2283 
SetDefaultLabel(LabelIdx idx)2284     void SetDefaultLabel(LabelIdx idx)
2285     {
2286         defaultLabel = idx;
2287     }
2288 
GetSwitchTable()2289     const CaseVector &GetSwitchTable() const
2290     {
2291         return switchTable;
2292     }
2293 
GetSwitchTable()2294     CaseVector &GetSwitchTable()
2295     {
2296         return switchTable;
2297     }
2298 
GetCasePair(size_t idx)2299     CasePair GetCasePair(size_t idx) const
2300     {
2301         DEBUG_ASSERT(idx < switchTable.size(), "out of range in SwitchNode::GetCasePair");
2302         return switchTable.at(idx);
2303     }
2304 
SetSwitchTable(CaseVector vec)2305     void SetSwitchTable(CaseVector vec)
2306     {
2307         switchTable = vec;
2308     }
2309 
InsertCasePair(CasePair pair)2310     void InsertCasePair(CasePair pair)
2311     {
2312         switchTable.push_back(pair);
2313     }
2314 
UpdateCaseLabelAt(size_t i,LabelIdx idx)2315     void UpdateCaseLabelAt(size_t i, LabelIdx idx)
2316     {
2317         switchTable[i] = std::make_pair(switchTable[i].first, idx);
2318     }
2319 
SortCasePair(bool func (const CasePair &,const CasePair &))2320     void SortCasePair(bool func(const CasePair &, const CasePair &))
2321     {
2322         std::sort(switchTable.begin(), switchTable.end(), func);
2323     }
2324 
2325 private:
2326     BaseNode *switchOpnd = nullptr;
2327     LabelIdx defaultLabel = 0;
2328     CaseVector switchTable;
2329 };
2330 
2331 using MCasePair = std::pair<BaseNode *, LabelIdx>;
2332 using MCaseVector = MapleVector<MCasePair>;
2333 class MultiwayNode : public StmtNode {
2334 public:
MultiwayNode(MapleAllocator & allocator)2335     explicit MultiwayNode(MapleAllocator &allocator) : StmtNode(OP_multiway, 1), multiWayTable(allocator.Adapter()) {}
2336 
MultiwayNode(const MIRModule & mod)2337     explicit MultiwayNode(const MIRModule &mod) : MultiwayNode(mod.GetCurFuncCodeMPAllocator()) {}
2338 
MultiwayNode(MapleAllocator & allocator,LabelIdx label)2339     MultiwayNode(MapleAllocator &allocator, LabelIdx label)
2340         : StmtNode(OP_multiway, 1), defaultLabel(label), multiWayTable(allocator.Adapter())
2341     {
2342     }
2343 
MultiwayNode(const MIRModule & mod,LabelIdx label)2344     MultiwayNode(const MIRModule &mod, LabelIdx label) : MultiwayNode(mod.GetCurFuncCodeMPAllocator(), label) {}
2345 
MultiwayNode(MapleAllocator & allocator,const MultiwayNode & node)2346     MultiwayNode(MapleAllocator &allocator, const MultiwayNode &node)
2347         : StmtNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds, node.GetSrcPos(), node.GetOriginalID(),
2348                    node.GetStmtAttrs()),
2349           defaultLabel(node.defaultLabel),
2350           multiWayTable(allocator.Adapter())
2351     {
2352     }
2353 
MultiwayNode(const MIRModule & mod,const MultiwayNode & node)2354     MultiwayNode(const MIRModule &mod, const MultiwayNode &node) : MultiwayNode(mod.GetCurFuncCodeMPAllocator(), node)
2355     {
2356     }
2357 
2358     MultiwayNode(MultiwayNode &node) = delete;
2359     MultiwayNode &operator=(const MultiwayNode &node) = delete;
2360     virtual ~MultiwayNode() = default;
2361 
2362     void Dump(int32 indent) const override;
2363 
CloneTree(MapleAllocator & allocator)2364     MultiwayNode *CloneTree(MapleAllocator &allocator) const override
2365     {
2366         auto *nd = allocator.GetMemPool()->New<MultiwayNode>(allocator, *this);
2367         nd->multiWayOpnd = static_cast<BaseNode *>(multiWayOpnd->CloneTree(allocator));
2368         for (size_t i = 0; i < multiWayTable.size(); ++i) {
2369             BaseNode *node = multiWayTable[i].first->CloneTree(allocator);
2370             MCasePair pair(static_cast<BaseNode *>(node), multiWayTable[i].second);
2371             nd->multiWayTable.push_back(pair);
2372         }
2373         return nd;
2374     }
2375 
Opnd(size_t i)2376     BaseNode *Opnd(size_t i) const override
2377     {
2378         return *(&multiWayOpnd + static_cast<uint32>(i));
2379     }
2380 
GetMultiWayOpnd()2381     const BaseNode *GetMultiWayOpnd() const
2382     {
2383         return multiWayOpnd;
2384     }
2385 
SetMultiWayOpnd(BaseNode * multiwayOpndPara)2386     void SetMultiWayOpnd(BaseNode *multiwayOpndPara)
2387     {
2388         multiWayOpnd = multiwayOpndPara;
2389     }
2390 
SetDefaultlabel(LabelIdx defaultLabelPara)2391     void SetDefaultlabel(LabelIdx defaultLabelPara)
2392     {
2393         defaultLabel = defaultLabelPara;
2394     }
2395 
AppendElemToMultiWayTable(const MCasePair & mCasrPair)2396     void AppendElemToMultiWayTable(const MCasePair &mCasrPair)
2397     {
2398         multiWayTable.push_back(mCasrPair);
2399     }
2400 
GetMultiWayTable()2401     const MCaseVector &GetMultiWayTable() const
2402     {
2403         return multiWayTable;
2404     }
2405 
2406 private:
2407     BaseNode *multiWayOpnd = nullptr;
2408     LabelIdx defaultLabel = 0;
2409     MCaseVector multiWayTable;
2410 };
2411 
2412 // eval, throw, free, decref, incref, decrefreset, assertnonnull, igoto
2413 class UnaryStmtNode : public StmtNode {
2414 public:
UnaryStmtNode(Opcode o)2415     explicit UnaryStmtNode(Opcode o) : StmtNode(o, 1) {}
2416 
UnaryStmtNode(Opcode o,PrimType typ)2417     UnaryStmtNode(Opcode o, PrimType typ) : StmtNode(o, typ, 1) {}
2418 
UnaryStmtNode(Opcode o,PrimType typ,BaseNode * opnd)2419     UnaryStmtNode(Opcode o, PrimType typ, BaseNode *opnd) : StmtNode(o, typ, 1), uOpnd(opnd) {}
2420 
2421     virtual ~UnaryStmtNode() = default;
2422 
2423     using StmtNode::Dump;
2424     void Dump(int32 indent) const override;
2425     void DumpOpnd(const MIRModule &mod, int32 indent) const;
2426     void DumpOpnd(int32 indent) const;
2427 
Verify()2428     bool Verify() const override
2429     {
2430         return uOpnd->Verify();
2431     }
2432 
Verify(VerifyResult & verifyResult)2433     bool Verify(VerifyResult &verifyResult) const override
2434     {
2435         if (GetOpCode() == OP_throw && !VerifyThrowable(verifyResult)) {
2436             return false;
2437         }
2438         return uOpnd->Verify(verifyResult);
2439     }
2440 
CloneTree(MapleAllocator & allocator)2441     UnaryStmtNode *CloneTree(MapleAllocator &allocator) const override
2442     {
2443         auto *node = allocator.GetMemPool()->New<UnaryStmtNode>(*this);
2444         node->SetStmtID(stmtIDNext++);
2445         node->SetOpnd(uOpnd->CloneTree(allocator), 0);
2446         return node;
2447     }
2448 
IsLeaf()2449     bool IsLeaf() const override
2450     {
2451         return false;
2452     }
2453 
GetRHS()2454     BaseNode *GetRHS() const override
2455     {
2456         return Opnd(0);
2457     }
2458 
SetRHS(BaseNode * rhs)2459     virtual void SetRHS(BaseNode *rhs)
2460     {
2461         this->SetOpnd(rhs, 0);
2462     }
2463 
2464     BaseNode *Opnd(size_t i = 0) const override
2465     {
2466         (void)i;
2467         return uOpnd;
2468     }
2469 
SetOpnd(BaseNode * node,size_t)2470     void SetOpnd(BaseNode *node, size_t) override
2471     {
2472         uOpnd = node;
2473     }
2474 
2475 private:
2476     bool VerifyThrowable(VerifyResult &verifyResult) const;
2477 
2478     BaseNode *uOpnd = nullptr;
2479 };
2480 
2481 // dassign, maydassign
2482 class DassignNode : public UnaryStmtNode {
2483 public:
DassignNode()2484     DassignNode() : UnaryStmtNode(OP_dassign), stIdx() {}
2485 
DassignNode(PrimType typ)2486     explicit DassignNode(PrimType typ) : UnaryStmtNode(OP_dassign, typ), stIdx() {}
2487 
DassignNode(PrimType typ,BaseNode * opnd)2488     DassignNode(PrimType typ, BaseNode *opnd) : UnaryStmtNode(OP_dassign, typ, opnd), stIdx() {}
2489 
DassignNode(PrimType typ,BaseNode * opnd,StIdx idx,FieldID fieldID)2490     DassignNode(PrimType typ, BaseNode *opnd, StIdx idx, FieldID fieldID)
2491         : UnaryStmtNode(OP_dassign, typ, opnd), stIdx(idx), fieldID(fieldID)
2492     {
2493     }
2494 
DassignNode(BaseNode * opnd,StIdx idx,FieldID fieldID)2495     DassignNode(BaseNode *opnd, StIdx idx, FieldID fieldID) : DassignNode(kPtyInvalid, opnd, idx, fieldID) {}
2496 
2497     virtual ~DassignNode() = default;
2498 
2499     void Dump(int32 indent) const override;
2500     bool Verify() const override;
2501 
CloneTree(MapleAllocator & allocator)2502     DassignNode *CloneTree(MapleAllocator &allocator) const override
2503     {
2504         auto *node = allocator.GetMemPool()->New<DassignNode>(*this);
2505         node->SetStmtID(stmtIDNext++);
2506         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
2507         return node;
2508     }
2509 
NumOpnds()2510     size_t NumOpnds() const override
2511     {
2512         return 1;
2513     }
2514 
IsIdentityDassign()2515     bool IsIdentityDassign() const
2516     {
2517         BaseNode *rhs = GetRHS();
2518         if (rhs->GetOpCode() != OP_dread) {
2519             return false;
2520         }
2521         auto *dread = static_cast<AddrofNode *>(rhs);
2522         return (stIdx == dread->GetStIdx());
2523     }
2524 
GetRHS()2525     BaseNode *GetRHS() const override
2526     {
2527         return UnaryStmtNode::GetRHS();
2528     }
2529 
SetRHS(BaseNode * rhs)2530     void SetRHS(BaseNode *rhs) override
2531     {
2532         UnaryStmtNode::SetOpnd(rhs, 0);
2533     }
2534 
GetStIdx()2535     StIdx GetStIdx() const
2536     {
2537         return stIdx;
2538     }
SetStIdx(StIdx s)2539     void SetStIdx(StIdx s)
2540     {
2541         stIdx = s;
2542     }
2543 
GetFieldID()2544     const FieldID &GetFieldID() const
2545     {
2546         return fieldID;
2547     }
2548 
SetFieldID(FieldID f)2549     void SetFieldID(FieldID f)
2550     {
2551         fieldID = f;
2552     }
2553 
2554     bool AssigningVolatile(const MIRModule &mod) const;
2555 
2556 private:
2557     StIdx stIdx;
2558     FieldID fieldID = 0;
2559 };
2560 
2561 class DassignoffNode : public UnaryStmtNode {
2562 public:
DassignoffNode()2563     DassignoffNode() : UnaryStmtNode(OP_dassignoff), stIdx() {}
2564 
DassignoffNode(PrimType typ)2565     explicit DassignoffNode(PrimType typ) : UnaryStmtNode(OP_dassignoff, typ), stIdx() {}
2566 
DassignoffNode(PrimType typ,BaseNode * opnd)2567     DassignoffNode(PrimType typ, BaseNode *opnd) : UnaryStmtNode(OP_dassignoff, typ, opnd), stIdx() {}
2568 
DassignoffNode(const StIdx & lhsStIdx,int32 dOffset,PrimType rhsType,BaseNode * rhsNode)2569     DassignoffNode(const StIdx &lhsStIdx, int32 dOffset, PrimType rhsType, BaseNode *rhsNode)
2570         : DassignoffNode(rhsType, rhsNode)
2571     {
2572         stIdx = lhsStIdx;
2573         offset = dOffset;
2574     }
2575     virtual ~DassignoffNode() = default;
2576 
2577     void Dump(int32 indent) const override;
2578 
CloneTree(MapleAllocator & allocator)2579     DassignoffNode *CloneTree(MapleAllocator &allocator) const override
2580     {
2581         auto *node = allocator.GetMemPool()->New<DassignoffNode>(*this);
2582         node->SetStmtID(stmtIDNext++);
2583         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
2584         return node;
2585     }
2586 
NumOpnds()2587     size_t NumOpnds() const override
2588     {
2589         return 1;
2590     }
2591 
GetRHS()2592     BaseNode *GetRHS() const override
2593     {
2594         return UnaryStmtNode::GetRHS();
2595     }
2596 
SetRHS(BaseNode * rhs)2597     void SetRHS(BaseNode *rhs) override
2598     {
2599         UnaryStmtNode::SetOpnd(rhs, 0);
2600     }
2601 
2602 public:
2603     StIdx stIdx;
2604     int32 offset = 0;
2605 };
2606 
2607 class RegassignNode : public UnaryStmtNode {
2608 public:
RegassignNode()2609     RegassignNode() : UnaryStmtNode(OP_regassign) {}
2610 
RegassignNode(PrimType primType,PregIdx idx,BaseNode * opnd)2611     RegassignNode(PrimType primType, PregIdx idx, BaseNode *opnd)
2612         : UnaryStmtNode(OP_regassign, primType, opnd), regIdx(idx)
2613     {
2614     }
2615 
2616     virtual ~RegassignNode() = default;
2617 
2618     void Dump(int32 indent) const override;
2619     bool Verify() const override;
2620 
CloneTree(MapleAllocator & allocator)2621     RegassignNode *CloneTree(MapleAllocator &allocator) const override
2622     {
2623         auto *node = allocator.GetMemPool()->New<RegassignNode>(*this);
2624         node->SetStmtID(stmtIDNext++);
2625         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
2626         return node;
2627     }
2628 
GetRHS()2629     BaseNode *GetRHS() const override
2630     {
2631         return UnaryStmtNode::GetRHS();
2632     }
2633 
SetRHS(BaseNode * rhs)2634     void SetRHS(BaseNode *rhs) override
2635     {
2636         UnaryStmtNode::SetOpnd(rhs, 0);
2637     }
2638 
GetRegIdx()2639     PregIdx GetRegIdx() const
2640     {
2641         return regIdx;
2642     }
SetRegIdx(PregIdx idx)2643     void SetRegIdx(PregIdx idx)
2644     {
2645         regIdx = idx;
2646     }
2647 
2648 private:
2649     PregIdx regIdx = 0;  // 32bit, negative if special register
2650 };
2651 
2652 // brtrue and brfalse
2653 class CondGotoNode : public UnaryStmtNode {
2654 public:
2655     static const int32 probAll;
CondGotoNode(Opcode o)2656     explicit CondGotoNode(Opcode o) : CondGotoNode(o, 0, nullptr) {}
2657 
CondGotoNode(Opcode o,uint32 offset,BaseNode * opnd)2658     CondGotoNode(Opcode o, uint32 offset, BaseNode *opnd) : UnaryStmtNode(o, kPtyInvalid, opnd), offset(offset)
2659     {
2660         BaseNodeT::SetNumOpnds(kOperandNumUnary);
2661     }
2662 
2663     virtual ~CondGotoNode() = default;
2664 
2665     void Dump(int32 indent) const override;
2666     bool Verify() const override;
2667 
GetOffset()2668     uint32 GetOffset() const
2669     {
2670         return offset;
2671     }
2672 
SetOffset(uint32 offsetValue)2673     void SetOffset(uint32 offsetValue)
2674     {
2675         offset = offsetValue;
2676     }
2677 
IsBranchProbValid()2678     bool IsBranchProbValid() const
2679     {
2680         return branchProb > 0 && branchProb < probAll;
2681     }
2682 
GetBranchProb()2683     int32 GetBranchProb() const
2684     {
2685         return branchProb;
2686     }
2687 
SetBranchProb(int32 prob)2688     void SetBranchProb(int32 prob)
2689     {
2690         branchProb = prob;
2691     }
2692 
ReverseBranchProb()2693     void ReverseBranchProb()
2694     {
2695         if (IsBranchProbValid()) {
2696             branchProb = probAll - branchProb;
2697         }
2698     }
2699 
InvalidateBranchProb()2700     void InvalidateBranchProb()
2701     {
2702         if (IsBranchProbValid()) {
2703             branchProb = -1;
2704         }
2705     }
2706 
CloneTree(MapleAllocator & allocator)2707     CondGotoNode *CloneTree(MapleAllocator &allocator) const override
2708     {
2709         auto *node = allocator.GetMemPool()->New<CondGotoNode>(*this);
2710         node->SetStmtID(stmtIDNext++);
2711         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
2712         return node;
2713     }
2714 
2715 private:
2716     uint32 offset;
2717     int32 branchProb = -1;  // branch probability, a negative number indicates that the probability is invalid
2718 };
2719 
2720 using SmallCasePair = std::pair<uint16, uint32>;
2721 using SmallCaseVector = MapleVector<SmallCasePair>;
2722 class RangeGotoNode : public UnaryStmtNode {
2723 public:
RangeGotoNode(MapleAllocator & allocator)2724     explicit RangeGotoNode(MapleAllocator &allocator) : UnaryStmtNode(OP_rangegoto), rangegotoTable(allocator.Adapter())
2725     {
2726     }
2727 
RangeGotoNode(const MIRModule & mod)2728     explicit RangeGotoNode(const MIRModule &mod) : RangeGotoNode(mod.GetCurFuncCodeMPAllocator()) {}
2729 
RangeGotoNode(MapleAllocator & allocator,const RangeGotoNode & node)2730     RangeGotoNode(MapleAllocator &allocator, const RangeGotoNode &node)
2731         : UnaryStmtNode(node), tagOffset(node.tagOffset), rangegotoTable(allocator.Adapter())
2732     {
2733     }
2734 
RangeGotoNode(const MIRModule & mod,const RangeGotoNode & node)2735     RangeGotoNode(const MIRModule &mod, const RangeGotoNode &node)
2736         : RangeGotoNode(mod.GetCurFuncCodeMPAllocator(), node)
2737     {
2738     }
2739 
2740     RangeGotoNode(RangeGotoNode &node) = delete;
2741     RangeGotoNode &operator=(const RangeGotoNode &node) = delete;
2742     virtual ~RangeGotoNode() = default;
2743 
2744     void Dump(int32 indent) const override;
2745     bool Verify() const override;
CloneTree(MapleAllocator & allocator)2746     RangeGotoNode *CloneTree(MapleAllocator &allocator) const override
2747     {
2748         auto *node = allocator.GetMemPool()->New<RangeGotoNode>(allocator, *this);
2749         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
2750         for (size_t i = 0; i < rangegotoTable.size(); ++i) {
2751             node->rangegotoTable.push_back(rangegotoTable[i]);
2752         }
2753         return node;
2754     }
2755 
GetRangeGotoTable()2756     const SmallCaseVector &GetRangeGotoTable() const
2757     {
2758         return rangegotoTable;
2759     }
2760 
GetRangeGotoTableItem(size_t i)2761     const SmallCasePair &GetRangeGotoTableItem(size_t i) const
2762     {
2763         return rangegotoTable.at(i);
2764     }
2765 
SetRangeGotoTable(SmallCaseVector rt)2766     void SetRangeGotoTable(SmallCaseVector rt)
2767     {
2768         rangegotoTable = rt;
2769     }
2770 
AddRangeGoto(uint32 tag,LabelIdx idx)2771     void AddRangeGoto(uint32 tag, LabelIdx idx)
2772     {
2773         rangegotoTable.push_back(SmallCasePair(tag, idx));
2774     }
2775 
GetTagOffset()2776     int32 GetTagOffset() const
2777     {
2778         return tagOffset;
2779     }
2780 
SetTagOffset(int32 offset)2781     void SetTagOffset(int32 offset)
2782     {
2783         tagOffset = offset;
2784     }
2785 
2786 private:
2787     int32 tagOffset = 0;
2788     // add each tag to tagOffset field to get the actual tag values
2789     SmallCaseVector rangegotoTable;
2790 };
2791 
2792 class BlockNode : public StmtNode {
2793 public:
2794     using StmtNodes = PtrListRef<StmtNode>;
2795 
BlockNode()2796     BlockNode() : StmtNode(OP_block) {}
2797 
~BlockNode()2798     ~BlockNode()
2799     {
2800         stmtNodeList.clear();
2801     }
2802 
2803     void AddStatement(StmtNode *stmt);
2804     void AppendStatementsFromBlock(BlockNode &blk);
2805     void InsertFirst(StmtNode *stmt);  // Insert stmt as the first
2806     void InsertLast(StmtNode *stmt);   // Insert stmt as the last
2807     void ReplaceStmtWithBlock(StmtNode &stmtNode, BlockNode &blk);
2808     void ReplaceStmt1WithStmt2(const StmtNode *stmtNode1, StmtNode *stmtNode2);
2809     void RemoveStmt(const StmtNode *stmtNode1);
2810     void InsertBefore(const StmtNode *stmtNode1, StmtNode *stmtNode2);  // Insert ss2 before ss1 in current block.
2811     void InsertAfter(const StmtNode *stmtNode1, StmtNode *stmtNode2);   // Insert ss2 after ss1 in current block.
2812     // insert all the stmts in inblock to the current block after stmt1
2813     void InsertBlockAfter(BlockNode &inblock, const StmtNode *stmt1);
2814     void Dump(int32 indent, const MIRSymbolTable *theSymTab, MIRPregTable *thePregTab, bool withInfo, bool isFuncbody,
2815               MIRFlavor flavor) const;
2816     bool Verify() const override;
2817     bool Verify(VerifyResult &verifyResult) const override;
2818 
Dump(int32 indent)2819     void Dump(int32 indent) const override
2820     {
2821         Dump(indent, nullptr, nullptr, false, false, kFlavorUnknown);
2822     }
2823 
CloneTree(MapleAllocator & allocator)2824     BlockNode *CloneTree(MapleAllocator &allocator) const override
2825     {
2826         auto *blk = allocator.GetMemPool()->New<BlockNode>();
2827         blk->SetStmtID(stmtIDNext++);
2828         for (auto &stmt : stmtNodeList) {
2829             StmtNode *newStmt = static_cast<StmtNode *>(stmt.CloneTree(allocator));
2830             DEBUG_ASSERT(newStmt != nullptr, "null ptr check");
2831             newStmt->SetPrev(nullptr);
2832             newStmt->SetNext(nullptr);
2833             blk->AddStatement(newStmt);
2834         }
2835         return blk;
2836     }
2837 
CloneTreeWithSrcPosition(const MIRModule & mod)2838     BlockNode *CloneTreeWithSrcPosition(const MIRModule &mod)
2839     {
2840         MapleAllocator &allocator = mod.GetCurFuncCodeMPAllocator();
2841         auto *blk = allocator.GetMemPool()->New<BlockNode>();
2842         blk->SetStmtID(stmtIDNext++);
2843         for (auto &stmt : stmtNodeList) {
2844             StmtNode *newStmt = static_cast<StmtNode *>(stmt.CloneTree(allocator));
2845             DEBUG_ASSERT(newStmt != nullptr, "null ptr check");
2846             newStmt->SetSrcPos(stmt.GetSrcPos());
2847             newStmt->SetPrev(nullptr);
2848             newStmt->SetNext(nullptr);
2849             blk->AddStatement(newStmt);
2850         }
2851         return blk;
2852     }
2853 
2854     BlockNode *CloneTreeWithFreqs(MapleAllocator &allocator, std::unordered_map<uint32_t, uint64_t> &toFreqs,
2855                                   std::unordered_map<uint32_t, uint64_t> &fromFreqs, uint64_t numer, uint64_t denom,
2856                                   uint32_t updateOp);
2857 
IsEmpty()2858     bool IsEmpty() const
2859     {
2860         return stmtNodeList.empty();
2861     }
2862 
ResetBlock()2863     void ResetBlock()
2864     {
2865         stmtNodeList.clear();
2866     }
2867 
GetFirst()2868     StmtNode *GetFirst()
2869     {
2870         return &(stmtNodeList.front());
2871     }
2872 
GetFirst()2873     const StmtNode *GetFirst() const
2874     {
2875         return &(stmtNodeList.front());
2876     }
2877 
SetFirst(StmtNode * node)2878     void SetFirst(StmtNode *node)
2879     {
2880         stmtNodeList.update_front(node);
2881     }
2882 
GetLast()2883     StmtNode *GetLast()
2884     {
2885         return &(stmtNodeList.back());
2886     }
2887 
GetLast()2888     const StmtNode *GetLast() const
2889     {
2890         return &(stmtNodeList.back());
2891     }
2892 
SetLast(StmtNode * node)2893     void SetLast(StmtNode *node)
2894     {
2895         stmtNodeList.update_back(node);
2896     }
2897 
GetStmtNodes()2898     StmtNodes &GetStmtNodes()
2899     {
2900         return stmtNodeList;
2901     }
2902 
GetStmtNodes()2903     const StmtNodes &GetStmtNodes() const
2904     {
2905         return stmtNodeList;
2906     }
2907 
2908 private:
2909     StmtNodes stmtNodeList;
2910 };
2911 
2912 class IfStmtNode : public UnaryStmtNode {
2913 public:
IfStmtNode()2914     IfStmtNode() : UnaryStmtNode(OP_if)
2915     {
2916         numOpnds = kOperandNumTernary;
2917     }
2918 
2919     virtual ~IfStmtNode() = default;
2920 
2921     void Dump(int32 indent) const override;
2922     bool Verify() const override;
2923 
CloneTree(MapleAllocator & allocator)2924     IfStmtNode *CloneTree(MapleAllocator &allocator) const override
2925     {
2926         auto *node = allocator.GetMemPool()->New<IfStmtNode>(*this);
2927         node->SetStmtID(stmtIDNext++);
2928         node->SetOpnd(Opnd()->CloneTree(allocator), 0);
2929         node->thenPart = thenPart->CloneTree(allocator);
2930         if (elsePart != nullptr) {
2931             node->elsePart = elsePart->CloneTree(allocator);
2932         }
2933         node->SetMeStmtID(GetMeStmtID());
2934         return node;
2935     }
2936 
CloneTreeWithFreqs(MapleAllocator & allocator,std::unordered_map<uint32_t,uint64_t> & toFreqs,std::unordered_map<uint32_t,uint64_t> & fromFreqs,uint64_t numer,uint64_t denom,uint32_t updateOp)2937     IfStmtNode *CloneTreeWithFreqs(MapleAllocator &allocator, std::unordered_map<uint32_t, uint64_t> &toFreqs,
2938                                    std::unordered_map<uint32_t, uint64_t> &fromFreqs, uint64_t numer, uint64_t denom,
2939                                    uint32_t updateOp)
2940     {
2941         auto *node = allocator.GetMemPool()->New<IfStmtNode>(*this);
2942         node->SetStmtID(stmtIDNext++);
2943         node->SetOpnd(Opnd()->CloneTree(allocator), 0);
2944         if (fromFreqs.count(GetStmtID()) > 0) {
2945             uint64_t oldFreq = fromFreqs[GetStmtID()];
2946             uint64_t newFreq = numer == 0 ? 0 : (denom > 0 ? (oldFreq * numer / denom) : oldFreq);
2947             toFreqs[node->GetStmtID()] = (newFreq > 0 || numer == 0) ? newFreq : 1;
2948             if (updateOp & kUpdateOrigFreq) {
2949                 uint64_t left = ((oldFreq - newFreq) > 0 || oldFreq == 0) ? (oldFreq - newFreq) : 1;
2950                 fromFreqs[GetStmtID()] = left;
2951             }
2952         }
2953         node->thenPart = thenPart->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp);
2954         if (elsePart != nullptr) {
2955             node->elsePart = elsePart->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp);
2956         }
2957         node->SetMeStmtID(GetMeStmtID());
2958         return node;
2959     }
2960 
2961     BaseNode *Opnd(size_t i = kFirstOpnd) const override
2962     {
2963         if (i == kFirstOpnd) {
2964             return UnaryStmtNode::Opnd(kFirstOpnd);
2965         } else if (i == kSecondOpnd) {
2966             return thenPart;
2967         } else if (i == kThirdOpnd) {
2968             DEBUG_ASSERT(elsePart != nullptr, "IfStmtNode has wrong numOpnds field, the elsePart is nullptr");
2969             DEBUG_ASSERT(numOpnds == kOperandNumTernary,
2970                          "IfStmtNode has wrong numOpnds field, the elsePart is nullptr");
2971             return elsePart;
2972         }
2973         DEBUG_ASSERT(false, "IfStmtNode has wrong numOpnds field: %u", NumOpnds());
2974         return nullptr;
2975     }
2976 
GetThenPart()2977     BlockNode *GetThenPart() const
2978     {
2979         return thenPart;
2980     }
2981 
SetThenPart(BlockNode * node)2982     void SetThenPart(BlockNode *node)
2983     {
2984         thenPart = node;
2985     }
2986 
GetElsePart()2987     BlockNode *GetElsePart() const
2988     {
2989         return elsePart;
2990     }
2991 
SetElsePart(BlockNode * node)2992     void SetElsePart(BlockNode *node)
2993     {
2994         elsePart = node;
2995     }
2996 
NumOpnds()2997     size_t NumOpnds() const override
2998     {
2999         if (elsePart == nullptr) {
3000             return kOperandNumBinary;
3001         }
3002         return kOperandNumTernary;
3003     }
3004 
3005 private:
3006     BlockNode *thenPart = nullptr;
3007     BlockNode *elsePart = nullptr;
3008 };
3009 
3010 // for both while and dowhile
3011 class WhileStmtNode : public UnaryStmtNode {
3012 public:
WhileStmtNode(Opcode o)3013     explicit WhileStmtNode(Opcode o) : UnaryStmtNode(o)
3014     {
3015         BaseNodeT::SetNumOpnds(kOperandNumBinary);
3016     }
3017 
3018     virtual ~WhileStmtNode() = default;
3019 
3020     void Dump(int32 indent) const override;
3021     bool Verify() const override;
3022 
CloneTree(MapleAllocator & allocator)3023     WhileStmtNode *CloneTree(MapleAllocator &allocator) const override
3024     {
3025         auto *node = allocator.GetMemPool()->New<WhileStmtNode>(*this);
3026         node->SetStmtID(stmtIDNext++);
3027         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
3028         node->body = body->CloneTree(allocator);
3029         return node;
3030     }
3031 
CloneTreeWithFreqs(MapleAllocator & allocator,std::unordered_map<uint32_t,uint64_t> & toFreqs,std::unordered_map<uint32_t,uint64_t> & fromFreqs,uint64_t numer,uint64_t denom,uint32_t updateOp)3032     WhileStmtNode *CloneTreeWithFreqs(MapleAllocator &allocator, std::unordered_map<uint32_t, uint64_t> &toFreqs,
3033                                       std::unordered_map<uint32_t, uint64_t> &fromFreqs, uint64_t numer, uint64_t denom,
3034                                       uint32_t updateOp)
3035     {
3036         auto *node = allocator.GetMemPool()->New<WhileStmtNode>(*this);
3037         node->SetStmtID(stmtIDNext++);
3038         if (fromFreqs.count(GetStmtID()) > 0) {
3039             int64_t oldFreq = fromFreqs[GetStmtID()];
3040             int64_t newFreq = numer == 0 ? 0 : (denom > 0 ? (oldFreq * numer / denom) : oldFreq);
3041             toFreqs[node->GetStmtID()] = (newFreq > 0 || numer == 0) ? static_cast<uint64_t>(newFreq) : 1;
3042             if (updateOp & kUpdateOrigFreq) {
3043                 int64_t left = (oldFreq - newFreq) > 0 ? (oldFreq - newFreq) : 1;
3044                 fromFreqs[GetStmtID()] = left;
3045             }
3046         }
3047         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
3048         node->body = body->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp);
3049         return node;
3050     }
3051 
SetBody(BlockNode * node)3052     void SetBody(BlockNode *node)
3053     {
3054         body = node;
3055     }
3056 
GetBody()3057     BlockNode *GetBody() const
3058     {
3059         return body;
3060     }
3061 
3062     BaseNode *Opnd(size_t i = 0) const override
3063     {
3064         if (i == 0) {
3065             return UnaryStmtNode::Opnd();
3066         } else if (i == 1) {
3067             return body;
3068         }
3069         DEBUG_ASSERT(false, "WhileStmtNode has wrong numOpnds field: %u", NumOpnds());
3070         return nullptr;
3071     }
3072 
3073 private:
3074     BlockNode *body = nullptr;
3075 };
3076 
3077 class DoloopNode : public StmtNode {
3078 public:
DoloopNode()3079     DoloopNode() : DoloopNode(StIdx(), false, nullptr, nullptr, nullptr, nullptr) {}
3080 
DoloopNode(StIdx doVarStIdx,bool isPReg,BaseNode * startExp,BaseNode * contExp,BaseNode * incrExp,BlockNode * doBody)3081     DoloopNode(StIdx doVarStIdx, bool isPReg, BaseNode *startExp, BaseNode *contExp, BaseNode *incrExp,
3082                BlockNode *doBody)
3083         : StmtNode(OP_doloop, kOperandNumDoloop),
3084           doVarStIdx(doVarStIdx),
3085           isPreg(isPReg),
3086           startExpr(startExp),
3087           condExpr(contExp),
3088           incrExpr(incrExp),
3089           doBody(doBody)
3090     {
3091     }
3092 
3093     virtual ~DoloopNode() = default;
3094 
3095     void DumpDoVar(const MIRModule &mod) const;
3096     void Dump(int32 indent) const override;
3097     bool Verify() const override;
3098 
CloneTree(MapleAllocator & allocator)3099     DoloopNode *CloneTree(MapleAllocator &allocator) const override
3100     {
3101         auto *node = allocator.GetMemPool()->New<DoloopNode>(*this);
3102         node->SetStmtID(stmtIDNext++);
3103         node->SetStartExpr(startExpr->CloneTree(allocator));
3104         node->SetContExpr(GetCondExpr()->CloneTree(allocator));
3105         node->SetIncrExpr(GetIncrExpr()->CloneTree(allocator));
3106         node->SetDoBody(GetDoBody()->CloneTree(allocator));
3107         return node;
3108     }
3109 
CloneTreeWithFreqs(MapleAllocator & allocator,std::unordered_map<uint32_t,uint64_t> & toFreqs,std::unordered_map<uint32_t,uint64_t> & fromFreqs,uint64_t numer,uint64_t denom,uint32_t updateOp)3110     DoloopNode *CloneTreeWithFreqs(MapleAllocator &allocator, std::unordered_map<uint32_t, uint64_t> &toFreqs,
3111                                    std::unordered_map<uint32_t, uint64_t> &fromFreqs, uint64_t numer, uint64_t denom,
3112                                    uint32_t updateOp)
3113     {
3114         auto *node = allocator.GetMemPool()->New<DoloopNode>(*this);
3115         node->SetStmtID(stmtIDNext++);
3116         if (fromFreqs.count(GetStmtID()) > 0) {
3117             uint64_t oldFreq = fromFreqs[GetStmtID()];
3118             uint64_t newFreq = oldFreq;
3119             if (updateOp & kUpdateFreqbyScale) {  // used in inline/clone
3120                 newFreq = numer == 0 ? 0 : (denom > 0 ? (oldFreq * numer / denom) : oldFreq);
3121             } else if (updateOp & kUpdateUnrolledFreq) {  // used in unrolled part
3122                 uint64_t bodyFreq = fromFreqs[GetDoBody()->GetStmtID()];
3123                 newFreq = denom > 0 ? (bodyFreq * numer / denom + (oldFreq - bodyFreq)) : oldFreq;
3124             } else if (updateOp & kUpdateUnrollRemainderFreq) {  // used in unrolled remainder
3125                 uint64_t bodyFreq = fromFreqs[GetDoBody()->GetStmtID()];
3126                 newFreq = denom > 0 ? (((bodyFreq * numer) % denom) + (oldFreq - bodyFreq)) : oldFreq;
3127             }
3128             toFreqs[node->GetStmtID()] = static_cast<uint64_t>(newFreq);
3129             DEBUG_ASSERT(oldFreq >= newFreq, "sanity check");
3130             if (updateOp & kUpdateOrigFreq) {
3131                 uint64_t left = oldFreq - newFreq;
3132                 fromFreqs[GetStmtID()] = left;
3133             }
3134         }
3135         node->SetStartExpr(startExpr->CloneTree(allocator));
3136         node->SetContExpr(GetCondExpr()->CloneTree(allocator));
3137         node->SetIncrExpr(GetIncrExpr()->CloneTree(allocator));
3138         node->SetDoBody(GetDoBody()->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp));
3139         return node;
3140     }
3141 
SetDoVarStIdx(StIdx idx)3142     void SetDoVarStIdx(StIdx idx)
3143     {
3144         doVarStIdx = idx;
3145     }
3146 
GetDoVarPregIdx()3147     PregIdx GetDoVarPregIdx() const
3148     {
3149         return static_cast<PregIdx>(doVarStIdx.FullIdx());
3150     }
3151 
GetDoVarStIdx()3152     const StIdx &GetDoVarStIdx() const
3153     {
3154         return doVarStIdx;
3155     }
3156 
SetDoVarStFullIdx(uint32 idx)3157     void SetDoVarStFullIdx(uint32 idx)
3158     {
3159         doVarStIdx.SetFullIdx(idx);
3160     }
3161 
SetIsPreg(bool isPregVal)3162     void SetIsPreg(bool isPregVal)
3163     {
3164         isPreg = isPregVal;
3165     }
3166 
IsPreg()3167     bool IsPreg() const
3168     {
3169         return isPreg;
3170     }
3171 
SetStartExpr(BaseNode * node)3172     void SetStartExpr(BaseNode *node)
3173     {
3174         startExpr = node;
3175     }
3176 
GetStartExpr()3177     BaseNode *GetStartExpr() const
3178     {
3179         return startExpr;
3180     }
3181 
SetContExpr(BaseNode * node)3182     void SetContExpr(BaseNode *node)
3183     {
3184         condExpr = node;
3185     }
3186 
GetCondExpr()3187     BaseNode *GetCondExpr() const
3188     {
3189         return condExpr;
3190     }
3191 
SetIncrExpr(BaseNode * node)3192     void SetIncrExpr(BaseNode *node)
3193     {
3194         incrExpr = node;
3195     }
3196 
GetIncrExpr()3197     BaseNode *GetIncrExpr() const
3198     {
3199         return incrExpr;
3200     }
3201 
SetDoBody(BlockNode * node)3202     void SetDoBody(BlockNode *node)
3203     {
3204         doBody = node;
3205     }
3206 
GetDoBody()3207     BlockNode *GetDoBody() const
3208     {
3209         return doBody;
3210     }
3211 
Opnd(size_t i)3212     BaseNode *Opnd(size_t i) const override
3213     {
3214         if (i == kFirstOpnd) {
3215             return startExpr;
3216         }
3217         if (i == kSecondOpnd) {
3218             return condExpr;
3219         }
3220         if (i == kThirdOpnd) {
3221             return incrExpr;
3222         }
3223         return *(&doBody + i - kOpndNum);
3224     }
3225 
NumOpnds()3226     size_t NumOpnds() const override
3227     {
3228         return kOperandNumDoloop;
3229     }
3230 
SetOpnd(BaseNode * node,size_t i)3231     void SetOpnd(BaseNode *node, size_t i) override
3232     {
3233         if (i == kFirstOpnd) {
3234             startExpr = node;
3235         }
3236         if (i == kSecondOpnd) {
3237             SetContExpr(node);
3238         }
3239         if (i == kThirdOpnd) {
3240             incrExpr = node;
3241         } else {
3242             *(&doBody + i - kOpndNum) = static_cast<BlockNode *>(node);
3243         }
3244     }
3245 
3246 private:
3247     static constexpr int kOperandNumDoloop = 4;
3248     StIdx doVarStIdx;  // must be local; cast to PregIdx for preg
3249     bool isPreg;
3250     BaseNode *startExpr;
3251     BaseNode *condExpr;
3252     BaseNode *incrExpr;
3253     BlockNode *doBody;
3254 };
3255 
3256 class ForeachelemNode : public StmtNode {
3257 public:
ForeachelemNode()3258     ForeachelemNode() : StmtNode(OP_foreachelem)
3259     {
3260         BaseNodeT::SetNumOpnds(kOperandNumUnary);
3261     }
3262 
3263     virtual ~ForeachelemNode() = default;
3264 
GetElemStIdx()3265     const StIdx &GetElemStIdx() const
3266     {
3267         return elemStIdx;
3268     }
3269 
SetElemStIdx(StIdx elemStIdxValue)3270     void SetElemStIdx(StIdx elemStIdxValue)
3271     {
3272         elemStIdx = elemStIdxValue;
3273     }
3274 
GetArrayStIdx()3275     const StIdx &GetArrayStIdx() const
3276     {
3277         return arrayStIdx;
3278     }
3279 
SetArrayStIdx(StIdx arrayStIdxValue)3280     void SetArrayStIdx(StIdx arrayStIdxValue)
3281     {
3282         arrayStIdx = arrayStIdxValue;
3283     }
3284 
GetLoopBody()3285     BlockNode *GetLoopBody() const
3286     {
3287         return loopBody;
3288     }
3289 
SetLoopBody(BlockNode * loopBodyValue)3290     void SetLoopBody(BlockNode *loopBodyValue)
3291     {
3292         loopBody = loopBodyValue;
3293     }
3294 
Opnd(size_t)3295     BaseNode *Opnd(size_t) const override
3296     {
3297         return loopBody;
3298     }
3299 
NumOpnds()3300     size_t NumOpnds() const override
3301     {
3302         return numOpnds;
3303     }
3304 
3305     void Dump(int32 indent) const override;
3306 
CloneTree(MapleAllocator & allocator)3307     ForeachelemNode *CloneTree(MapleAllocator &allocator) const override
3308     {
3309         auto *node = allocator.GetMemPool()->New<ForeachelemNode>(*this);
3310         node->SetStmtID(stmtIDNext++);
3311         node->SetLoopBody(loopBody->CloneTree(allocator));
3312         return node;
3313     }
3314 
3315 private:
3316     StIdx elemStIdx;   // must be local symbol
3317     StIdx arrayStIdx;  // symbol table entry of the array/collection variable
3318     BlockNode *loopBody = nullptr;
3319 };
3320 
3321 // used by assertge, assertlt
3322 class BinaryStmtNode : public StmtNode, public BinaryOpnds {
3323 public:
BinaryStmtNode(Opcode o)3324     explicit BinaryStmtNode(Opcode o) : StmtNode(o, kOperandNumBinary) {}
3325 
3326     virtual ~BinaryStmtNode() = default;
3327 
3328     void Dump(int32 indent) const override;
3329     bool Verify() const override;
CloneTree(MapleAllocator & allocator)3330     BinaryStmtNode *CloneTree(MapleAllocator &allocator) const override
3331     {
3332         auto *node = allocator.GetMemPool()->New<BinaryStmtNode>(*this);
3333         node->SetStmtID(stmtIDNext++);
3334         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
3335         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
3336         return node;
3337     }
3338 
Opnd(size_t i)3339     BaseNode *Opnd(size_t i) const override
3340     {
3341         DEBUG_ASSERT(i < kOperandNumBinary, "Invalid operand idx in BinaryStmtNode");
3342         DEBUG_ASSERT(i >= 0, "Invalid operand idx in BinaryStmtNode");
3343         return GetBOpnd(i);
3344     }
3345 
NumOpnds()3346     size_t NumOpnds() const override
3347     {
3348         return kOperandNumBinary;
3349     }
3350 
SetOpnd(BaseNode * node,size_t i)3351     void SetOpnd(BaseNode *node, size_t i) override
3352     {
3353         SetBOpnd(node, i);
3354     }
3355 
IsLeaf()3356     bool IsLeaf() const override
3357     {
3358         return false;
3359     }
3360 };
3361 
3362 class IassignoffNode : public BinaryStmtNode {
3363 public:
IassignoffNode()3364     IassignoffNode() : BinaryStmtNode(OP_iassignoff) {}
3365 
IassignoffNode(int32 ofst)3366     explicit IassignoffNode(int32 ofst) : BinaryStmtNode(OP_iassignoff), offset(ofst) {}
3367 
IassignoffNode(PrimType primType,int32 offset,BaseNode * addrOpnd,BaseNode * srcOpnd)3368     IassignoffNode(PrimType primType, int32 offset, BaseNode *addrOpnd, BaseNode *srcOpnd) : IassignoffNode(offset)
3369     {
3370         BaseNodeT::SetPrimType(primType);
3371         SetBOpnd(addrOpnd, 0);
3372         SetBOpnd(srcOpnd, 1);
3373     }
3374 
3375     virtual ~IassignoffNode() = default;
3376 
3377     void Dump(int32 indent) const override;
3378     bool Verify() const override;
3379 
CloneTree(MapleAllocator & allocator)3380     IassignoffNode *CloneTree(MapleAllocator &allocator) const override
3381     {
3382         auto *node = allocator.GetMemPool()->New<IassignoffNode>(*this);
3383         node->SetStmtID(stmtIDNext++);
3384         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
3385         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
3386         return node;
3387     }
3388 
GetOffset()3389     int32 GetOffset() const
3390     {
3391         return offset;
3392     }
3393 
SetOffset(int32 newOffset)3394     void SetOffset(int32 newOffset)
3395     {
3396         offset = newOffset;
3397     }
3398 
3399 private:
3400     int32 offset = 0;
3401 };
3402 
3403 // for iassignfpoff, iassignspoff, iassignpcoff
3404 class IassignFPoffNode : public UnaryStmtNode {
3405 public:
IassignFPoffNode(Opcode o)3406     IassignFPoffNode(Opcode o) : UnaryStmtNode(o) {}
3407 
IassignFPoffNode(Opcode o,int32 ofst)3408     explicit IassignFPoffNode(Opcode o, int32 ofst) : UnaryStmtNode(o), offset(ofst) {}
3409 
IassignFPoffNode(Opcode o,PrimType primType,int32 offset,BaseNode * src)3410     IassignFPoffNode(Opcode o, PrimType primType, int32 offset, BaseNode *src) : IassignFPoffNode(o, offset)
3411     {
3412         BaseNodeT::SetPrimType(primType);
3413         UnaryStmtNode::SetOpnd(src, 0);
3414     }
3415 
3416     virtual ~IassignFPoffNode() = default;
3417 
3418     void Dump(int32 indent) const override;
3419     bool Verify() const override;
3420 
CloneTree(MapleAllocator & allocator)3421     IassignFPoffNode *CloneTree(MapleAllocator &allocator) const override
3422     {
3423         auto *node = allocator.GetMemPool()->New<IassignFPoffNode>(*this);
3424         node->SetStmtID(stmtIDNext++);
3425         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
3426         return node;
3427     }
3428 
SetOffset(int32 ofst)3429     void SetOffset(int32 ofst)
3430     {
3431         offset = ofst;
3432     }
3433 
GetOffset()3434     int32 GetOffset() const
3435     {
3436         return offset;
3437     }
3438 
3439 private:
3440     int32 offset = 0;
3441 };
3442 
3443 typedef IassignFPoffNode IassignPCoffNode;
3444 
3445 class BlkassignoffNode : public BinaryStmtNode {
3446 public:
BlkassignoffNode()3447     BlkassignoffNode() : BinaryStmtNode(OP_blkassignoff)
3448     {
3449         ptyp = PTY_agg;
3450         ptyp = PTY_agg;
3451         alignLog2 = 0;
3452         offset = 0;
3453     }
BlkassignoffNode(int32 ofst,int32 bsize)3454     explicit BlkassignoffNode(int32 ofst, int32 bsize) : BinaryStmtNode(OP_blkassignoff), offset(ofst), blockSize(bsize)
3455     {
3456         ptyp = PTY_agg;
3457         alignLog2 = 0;
3458     }
BlkassignoffNode(int32 ofst,int32 bsize,BaseNode * dest,BaseNode * src)3459     explicit BlkassignoffNode(int32 ofst, int32 bsize, BaseNode *dest, BaseNode *src)
3460         : BinaryStmtNode(OP_blkassignoff), offset(ofst), blockSize(bsize)
3461     {
3462         ptyp = PTY_agg;
3463         alignLog2 = 0;
3464         SetBOpnd(dest, 0);
3465         SetBOpnd(src, 1);
3466     }
3467     ~BlkassignoffNode() = default;
3468 
3469     void Dump(int32 indent) const override;
3470 
CloneTree(MapleAllocator & allocator)3471     BlkassignoffNode *CloneTree(MapleAllocator &allocator) const override
3472     {
3473         BlkassignoffNode *node = allocator.GetMemPool()->New<BlkassignoffNode>(offset, blockSize);
3474         node->SetStmtID(stmtIDNext++);
3475         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
3476         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
3477         return node;
3478     }
3479 
GetAlign()3480     uint32 GetAlign() const
3481     {
3482         uint32 res = 1;
3483         for (uint32 i = 0; i < alignLog2; i++) {
3484             res <<= 1;
3485         }
3486         return res;
3487     }
3488 
SetAlign(uint32 x)3489     void SetAlign(uint32 x)
3490     {
3491         if (x == 0) {
3492             alignLog2 = 0;
3493             return;
3494         }
3495         DEBUG_ASSERT((~(x - 1) & x) == x, "SetAlign called with non power of 2");
3496         uint32 res = 0;
3497         while (x != 1) {
3498             x >>= 1;
3499             ++res;
3500         }
3501         alignLog2 = res;
3502     }
3503 
3504     uint32 alignLog2 : 4;
3505     int32 offset : 28;
3506     int32 blockSize = 0;
3507 };
3508 
3509 // used by return, syncenter, syncexit
3510 class NaryStmtNode : public StmtNode, public NaryOpnds {
3511 public:
NaryStmtNode(MapleAllocator & allocator,Opcode o)3512     NaryStmtNode(MapleAllocator &allocator, Opcode o) : StmtNode(o), NaryOpnds(allocator) {}
3513 
NaryStmtNode(const MIRModule & mod,Opcode o)3514     NaryStmtNode(const MIRModule &mod, Opcode o) : NaryStmtNode(mod.GetCurFuncCodeMPAllocator(), o) {}
3515 
NaryStmtNode(MapleAllocator & allocator,const NaryStmtNode & node)3516     NaryStmtNode(MapleAllocator &allocator, const NaryStmtNode &node)
3517         // do not use stmt copy constructor
3518         : StmtNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds, node.GetSrcPos(), node.GetOriginalID(),
3519                    node.GetStmtAttrs()),
3520           NaryOpnds(allocator)
3521     {
3522     }
3523 
NaryStmtNode(const MIRModule & mod,const NaryStmtNode & node)3524     NaryStmtNode(const MIRModule &mod, const NaryStmtNode &node) : NaryStmtNode(mod.GetCurFuncCodeMPAllocator(), node)
3525     {
3526     }
3527 
3528     explicit NaryStmtNode(const NaryStmtNode &node) = delete;
3529     NaryStmtNode &operator=(const NaryStmtNode &node) = delete;
3530     virtual ~NaryStmtNode() = default;
3531 
3532     void Dump(int32 indent) const override;
DumpCallConvInfo()3533     void DumpCallConvInfo() const
3534     {
3535         if (GetAttr(STMTATTR_ccall)) {
3536             LogInfo::MapleLogger() << " ccall";
3537         } else if (GetAttr(STMTATTR_webkitjscall)) {
3538             LogInfo::MapleLogger() << " webkitjscc";
3539         } else if (GetAttr(STMTATTR_ghcall)) {
3540             LogInfo::MapleLogger() << " ghccc";
3541         } else {
3542             // default is ccall
3543             LogInfo::MapleLogger() << " ccall";
3544         }
3545     }
3546     bool Verify() const override;
3547 
CloneTree(MapleAllocator & allocator)3548     NaryStmtNode *CloneTree(MapleAllocator &allocator) const override
3549     {
3550         auto *node = allocator.GetMemPool()->New<NaryStmtNode>(allocator, *this);
3551         for (size_t i = 0; i < GetNopndSize(); ++i) {
3552             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
3553         }
3554         node->SetNumOpnds(GetNopndSize());
3555         return node;
3556     }
3557 
Opnd(size_t i)3558     BaseNode *Opnd(size_t i) const override
3559     {
3560         return GetNopndAt(i);
3561     }
3562 
SetOpnd(BaseNode * node,size_t i)3563     void SetOpnd(BaseNode *node, size_t i) override
3564     {
3565         DEBUG_ASSERT(i < GetNopnd().size(), "array index out of range");
3566         SetNOpndAt(i, node);
3567     }
3568 
NumOpnds()3569     size_t NumOpnds() const override
3570     {
3571         DEBUG_ASSERT(numOpnds == GetNopndSize(), "NaryStmtNode has wrong numOpnds field");
3572         return GetNopndSize();
3573     }
3574 
SetOpnds(const MapleVector<BaseNode * > & arguments)3575     void SetOpnds(const MapleVector<BaseNode *> &arguments)
3576     {
3577         SetNOpnd(arguments);
3578         SetNumOpnds(arguments.size());
3579     }
3580 
PushOpnd(BaseNode * node)3581     void PushOpnd(BaseNode *node)
3582     {
3583         if (node != nullptr) {
3584             GetNopnd().push_back(node);
3585         }
3586         SetNumOpnds(GetNopndSize());
3587     }
3588 
InsertOpnd(BaseNode * node,size_t idx)3589     void InsertOpnd(BaseNode *node, size_t idx)
3590     {
3591         if (node == nullptr || idx > GetNopndSize()) {
3592             return;
3593         }
3594         auto begin = GetNopnd().begin();
3595         for (size_t i = 0; i < idx; ++i) {
3596             ++begin;
3597         }
3598         (void)GetNopnd().insert(begin, node);
3599         SetNumOpnds(GetNopndSize());
3600     }
3601 };
3602 
3603 class SafetyCheckStmtNode {
3604 public:
SafetyCheckStmtNode(GStrIdx funcNameIdx)3605     explicit SafetyCheckStmtNode(GStrIdx funcNameIdx) : funcNameIdx(funcNameIdx) {}
SafetyCheckStmtNode(const SafetyCheckStmtNode & stmtNode)3606     explicit SafetyCheckStmtNode(const SafetyCheckStmtNode &stmtNode) : funcNameIdx(stmtNode.GetFuncNameIdx()) {}
3607 
3608     virtual ~SafetyCheckStmtNode() = default;
3609 
3610     std::string GetFuncName() const;
3611 
GetFuncNameIdx()3612     GStrIdx GetFuncNameIdx() const
3613     {
3614         return funcNameIdx;
3615     }
3616 
Dump()3617     void Dump() const
3618     {
3619         LogInfo::MapleLogger() << " <&" << GetFuncName() << ">";
3620     }
3621 
3622 private:
3623     GStrIdx funcNameIdx;
3624 };
3625 
3626 // used by callassertnonnull, callassertle
3627 class SafetyCallCheckStmtNode {
3628 public:
SafetyCallCheckStmtNode(GStrIdx callFuncNameIdx,size_t paramIndex,GStrIdx stmtFuncNameIdx)3629     SafetyCallCheckStmtNode(GStrIdx callFuncNameIdx, size_t paramIndex, GStrIdx stmtFuncNameIdx)
3630         : callFuncNameIdx(callFuncNameIdx), paramIndex(paramIndex), stmtFuncNameIdx(stmtFuncNameIdx)
3631     {
3632     }
SafetyCallCheckStmtNode(const SafetyCallCheckStmtNode & stmtNode)3633     explicit SafetyCallCheckStmtNode(const SafetyCallCheckStmtNode &stmtNode)
3634         : callFuncNameIdx(stmtNode.GetFuncNameIdx()),
3635           paramIndex(stmtNode.GetParamIndex()),
3636           stmtFuncNameIdx(stmtNode.GetStmtFuncNameIdx())
3637     {
3638     }
3639 
3640     virtual ~SafetyCallCheckStmtNode() = default;
3641 
3642     std::string GetFuncName() const;
GetFuncNameIdx()3643     GStrIdx GetFuncNameIdx() const
3644     {
3645         return callFuncNameIdx;
3646     }
3647     std::string GetStmtFuncName() const;
GetParamIndex()3648     size_t GetParamIndex() const
3649     {
3650         return paramIndex;
3651     }
3652 
GetStmtFuncNameIdx()3653     GStrIdx GetStmtFuncNameIdx() const
3654     {
3655         return stmtFuncNameIdx;
3656     }
3657 
Dump()3658     void Dump() const
3659     {
3660         LogInfo::MapleLogger() << " <&" << GetFuncName() << ", " << paramIndex << ", &" << GetStmtFuncName() << ">";
3661     }
3662 
3663 private:
3664     GStrIdx callFuncNameIdx;
3665     size_t paramIndex;
3666     GStrIdx stmtFuncNameIdx;
3667 };
3668 
3669 // used by callassertnonnull
3670 class CallAssertNonnullStmtNode : public UnaryStmtNode, public SafetyCallCheckStmtNode {
3671 public:
CallAssertNonnullStmtNode(Opcode o,GStrIdx callFuncNameIdx,size_t paramIndex,GStrIdx stmtFuncNameIdx)3672     CallAssertNonnullStmtNode(Opcode o, GStrIdx callFuncNameIdx, size_t paramIndex, GStrIdx stmtFuncNameIdx)
3673         : UnaryStmtNode(o), SafetyCallCheckStmtNode(callFuncNameIdx, paramIndex, stmtFuncNameIdx)
3674     {
3675     }
~CallAssertNonnullStmtNode()3676     virtual ~CallAssertNonnullStmtNode() {}
3677 
3678     void Dump(int32 indent) const override;
3679 
CloneTree(MapleAllocator & allocator)3680     CallAssertNonnullStmtNode *CloneTree(MapleAllocator &allocator) const override
3681     {
3682         auto *node = allocator.GetMemPool()->New<CallAssertNonnullStmtNode>(*this);
3683         node->SetStmtID(stmtIDNext++);
3684         node->SetOpnd(Opnd()->CloneTree(allocator), 0);
3685         return node;
3686     }
3687 };
3688 
3689 // used by assertnonnull
3690 class AssertNonnullStmtNode : public UnaryStmtNode, public SafetyCheckStmtNode {
3691 public:
AssertNonnullStmtNode(Opcode o,GStrIdx funcNameIdx)3692     AssertNonnullStmtNode(Opcode o, GStrIdx funcNameIdx) : UnaryStmtNode(o), SafetyCheckStmtNode(funcNameIdx) {}
~AssertNonnullStmtNode()3693     virtual ~AssertNonnullStmtNode() {}
3694 
3695     void Dump(int32 indent) const override;
3696 
CloneTree(MapleAllocator & allocator)3697     AssertNonnullStmtNode *CloneTree(MapleAllocator &allocator) const override
3698     {
3699         auto *node = allocator.GetMemPool()->New<AssertNonnullStmtNode>(*this);
3700         node->SetStmtID(stmtIDNext++);
3701         node->SetOpnd(Opnd()->CloneTree(allocator), 0);
3702         return node;
3703     }
3704 };
3705 
3706 // used by assertle
3707 class AssertBoundaryStmtNode : public NaryStmtNode, public SafetyCheckStmtNode {
3708 public:
AssertBoundaryStmtNode(MapleAllocator & allocator,Opcode o,GStrIdx funcNameIdx)3709     AssertBoundaryStmtNode(MapleAllocator &allocator, Opcode o, GStrIdx funcNameIdx)
3710         : NaryStmtNode(allocator, o), SafetyCheckStmtNode(funcNameIdx)
3711     {
3712     }
~AssertBoundaryStmtNode()3713     virtual ~AssertBoundaryStmtNode() {}
3714 
AssertBoundaryStmtNode(MapleAllocator & allocator,const AssertBoundaryStmtNode & stmtNode)3715     AssertBoundaryStmtNode(MapleAllocator &allocator, const AssertBoundaryStmtNode &stmtNode)
3716         : NaryStmtNode(allocator, stmtNode), SafetyCheckStmtNode(stmtNode)
3717     {
3718     }
3719 
AssertBoundaryStmtNode(const MIRModule & mod,Opcode o,GStrIdx funcNameIdx)3720     AssertBoundaryStmtNode(const MIRModule &mod, Opcode o, GStrIdx funcNameIdx)
3721         : AssertBoundaryStmtNode(mod.GetCurFuncCodeMPAllocator(), o, funcNameIdx)
3722     {
3723     }
3724 
3725     void Dump(int32 indent) const override;
3726 
CloneTree(MapleAllocator & allocator)3727     AssertBoundaryStmtNode *CloneTree(MapleAllocator &allocator) const override
3728     {
3729         auto *node = allocator.GetMemPool()->New<AssertBoundaryStmtNode>(allocator, *this);
3730         node->SetStmtID(stmtIDNext++);
3731         for (size_t i = 0; i < GetNopndSize(); ++i) {
3732             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
3733         }
3734         node->SetNumOpnds(GetNopndSize());
3735         return node;
3736     }
3737 };
3738 
3739 // used by callassertle
3740 class CallAssertBoundaryStmtNode : public NaryStmtNode, public SafetyCallCheckStmtNode {
3741 public:
CallAssertBoundaryStmtNode(MapleAllocator & allocator,Opcode o,GStrIdx funcNameIdx,size_t paramIndex,GStrIdx stmtFuncNameIdx)3742     CallAssertBoundaryStmtNode(MapleAllocator &allocator, Opcode o, GStrIdx funcNameIdx, size_t paramIndex,
3743                                GStrIdx stmtFuncNameIdx)
3744         : NaryStmtNode(allocator, o), SafetyCallCheckStmtNode(funcNameIdx, paramIndex, stmtFuncNameIdx)
3745     {
3746     }
~CallAssertBoundaryStmtNode()3747     virtual ~CallAssertBoundaryStmtNode() {}
3748 
CallAssertBoundaryStmtNode(MapleAllocator & allocator,const CallAssertBoundaryStmtNode & stmtNode)3749     CallAssertBoundaryStmtNode(MapleAllocator &allocator, const CallAssertBoundaryStmtNode &stmtNode)
3750         : NaryStmtNode(allocator, stmtNode), SafetyCallCheckStmtNode(stmtNode)
3751     {
3752     }
3753 
CallAssertBoundaryStmtNode(const MIRModule & mod,Opcode o,GStrIdx funcNameIdx,size_t paramIndex,GStrIdx stmtFuncNameIdx)3754     CallAssertBoundaryStmtNode(const MIRModule &mod, Opcode o, GStrIdx funcNameIdx, size_t paramIndex,
3755                                GStrIdx stmtFuncNameIdx)
3756         : CallAssertBoundaryStmtNode(mod.GetCurFuncCodeMPAllocator(), o, funcNameIdx, paramIndex, stmtFuncNameIdx)
3757     {
3758     }
3759 
3760     void Dump(int32 indent) const override;
3761 
CloneTree(MapleAllocator & allocator)3762     CallAssertBoundaryStmtNode *CloneTree(MapleAllocator &allocator) const override
3763     {
3764         auto *node = allocator.GetMemPool()->New<CallAssertBoundaryStmtNode>(allocator, *this);
3765         node->SetStmtID(stmtIDNext++);
3766         for (size_t i = 0; i < GetNopndSize(); ++i) {
3767             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
3768         }
3769         node->SetNumOpnds(GetNopndSize());
3770         return node;
3771     }
3772 };
3773 
3774 // used by call, virtualcall, virtualicall, superclasscall, interfacecall,
3775 // interfaceicall, customcall
3776 // polymorphiccall
3777 // callassigned, virtualcallassigned, virtualicallassigned,
3778 // superclasscallassigned, interfacecallassigned, interfaceicallassigned,
3779 // customcallassigned
3780 // polymorphiccallassigned
3781 class CallNode : public NaryStmtNode, public DeoptBundleInfo {
3782 public:
CallNode(MapleAllocator & allocator,Opcode o)3783     CallNode(MapleAllocator &allocator, Opcode o)
3784         : NaryStmtNode(allocator, o), DeoptBundleInfo(allocator), returnValues(allocator.Adapter())
3785     {
3786     }
3787 
CallNode(MapleAllocator & allocator,Opcode o,PUIdx idx)3788     CallNode(MapleAllocator &allocator, Opcode o, PUIdx idx) : CallNode(allocator, o, idx, TyIdx()) {}
3789 
CallNode(MapleAllocator & allocator,Opcode o,PUIdx idx,TyIdx tdx)3790     CallNode(MapleAllocator &allocator, Opcode o, PUIdx idx, TyIdx tdx)
3791         : NaryStmtNode(allocator, o),
3792           DeoptBundleInfo(allocator),
3793           puIdx(idx),
3794           tyIdx(tdx),
3795           returnValues(allocator.Adapter())
3796     {
3797     }
3798 
CallNode(const MIRModule & mod,Opcode o)3799     CallNode(const MIRModule &mod, Opcode o) : CallNode(mod.GetCurFuncCodeMPAllocator(), o) {}
3800 
CallNode(const MIRModule & mod,Opcode o,PUIdx idx,TyIdx tdx)3801     CallNode(const MIRModule &mod, Opcode o, PUIdx idx, TyIdx tdx)
3802         : CallNode(mod.GetCurFuncCodeMPAllocator(), o, idx, tdx)
3803     {
3804     }
3805 
CallNode(MapleAllocator & allocator,const CallNode & node)3806     CallNode(MapleAllocator &allocator, const CallNode &node)
3807         : NaryStmtNode(allocator, node),
3808           DeoptBundleInfo(allocator),
3809           puIdx(node.GetPUIdx()),
3810           tyIdx(node.tyIdx),
3811           returnValues(allocator.Adapter())
3812     {
3813     }
3814 
CallNode(const MIRModule & mod,const CallNode & node)3815     CallNode(const MIRModule &mod, const CallNode &node) : CallNode(mod.GetCurFuncCodeMPAllocator(), node) {}
3816 
3817     CallNode(CallNode &node) = delete;
3818     CallNode &operator=(const CallNode &node) = delete;
3819     virtual ~CallNode() = default;
3820     virtual void Dump(int32 indent, bool newline) const;
3821     bool Verify() const override;
3822     MIRType *GetCallReturnType() override;
3823     const MIRSymbol *GetCallReturnSymbol(const MIRModule &mod) const;
3824 
CloneTree(MapleAllocator & allocator)3825     CallNode *CloneTree(MapleAllocator &allocator) const override
3826     {
3827         auto *node = allocator.GetMemPool()->New<CallNode>(allocator, *this);
3828         for (size_t i = 0; i < GetNopndSize(); ++i) {
3829             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
3830         }
3831         for (size_t i = 0; i < returnValues.size(); ++i) {
3832             node->GetReturnVec().push_back(returnValues[i]);
3833         }
3834         node->SetNumOpnds(GetNopndSize());
3835         for (const auto &elem : GetDeoptBundleInfo()) {
3836             node->AddDeoptBundleInfo(elem.first, elem.second);
3837         }
3838         return node;
3839     }
3840 
GetPUIdx()3841     PUIdx GetPUIdx() const
3842     {
3843         return puIdx;
3844     }
3845 
SetPUIdx(const PUIdx idx)3846     void SetPUIdx(const PUIdx idx)
3847     {
3848         puIdx = idx;
3849     }
3850 
GetTyIdx()3851     TyIdx GetTyIdx() const
3852     {
3853         return tyIdx;
3854     }
3855 
SetTyIdx(TyIdx idx)3856     void SetTyIdx(TyIdx idx)
3857     {
3858         tyIdx = idx;
3859     }
3860 
GetReturnVec()3861     CallReturnVector &GetReturnVec()
3862     {
3863         return returnValues;
3864     }
3865 
GetReturnPair(size_t idx)3866     CallReturnPair GetReturnPair(size_t idx) const
3867     {
3868         DEBUG_ASSERT(idx < returnValues.size(), "out of range in CallNode::GetReturnPair");
3869         return returnValues.at(idx);
3870     }
3871 
SetReturnPair(CallReturnPair retVal,size_t idx)3872     void SetReturnPair(CallReturnPair retVal, size_t idx)
3873     {
3874         DEBUG_ASSERT(idx < returnValues.size(), "out of range in CallNode::GetReturnPair");
3875         returnValues.at(idx) = retVal;
3876     }
3877 
GetReturnVec()3878     const CallReturnVector &GetReturnVec() const
3879     {
3880         return returnValues;
3881     }
3882 
GetNthReturnVec(size_t i)3883     CallReturnPair GetNthReturnVec(size_t i) const
3884     {
3885         DEBUG_ASSERT(i < returnValues.size(), "array index out of range");
3886         return returnValues[i];
3887     }
3888 
SetReturnVec(const CallReturnVector & vec)3889     void SetReturnVec(const CallReturnVector &vec)
3890     {
3891         returnValues = vec;
3892     }
3893 
NumOpnds()3894     size_t NumOpnds() const override
3895     {
3896         DEBUG_ASSERT(numOpnds == GetNopndSize(), "CallNode has wrong numOpnds field");
3897         return GetNopndSize();
3898     }
3899 
Dump(int32 indent)3900     void Dump(int32 indent) const override
3901     {
3902         Dump(indent, true);
3903     }
3904 
GetCallReturnVector()3905     CallReturnVector *GetCallReturnVector() override
3906     {
3907         return &returnValues;
3908     }
3909 
SetCallReturnVector(const CallReturnVector & value)3910     void SetCallReturnVector(const CallReturnVector &value)
3911     {
3912         returnValues = value;
3913     }
3914 
3915 private:
3916     PUIdx puIdx = 0;
3917     TyIdx tyIdx = TyIdx(0);
3918     CallReturnVector returnValues;
3919 };
3920 
3921 // icall, icallassigned, icallproto and icallprotoassigned
3922 class IcallNode : public NaryStmtNode, public DeoptBundleInfo {
3923 public:
IcallNode(MapleAllocator & allocator,Opcode o)3924     IcallNode(MapleAllocator &allocator, Opcode o)
3925         : NaryStmtNode(allocator, o), DeoptBundleInfo(allocator), retTyIdx(0), returnValues(allocator.Adapter())
3926     {
3927         BaseNodeT::SetNumOpnds(kOperandNumUnary);
3928     }
3929 
IcallNode(MapleAllocator & allocator,Opcode o,TyIdx idx)3930     IcallNode(MapleAllocator &allocator, Opcode o, TyIdx idx)
3931         : NaryStmtNode(allocator, o), DeoptBundleInfo(allocator), retTyIdx(idx), returnValues(allocator.Adapter())
3932     {
3933         BaseNodeT::SetNumOpnds(kOperandNumUnary);
3934     }
3935 
IcallNode(const MIRModule & mod,Opcode o)3936     IcallNode(const MIRModule &mod, Opcode o) : IcallNode(mod.GetCurFuncCodeMPAllocator(), o) {}
3937 
IcallNode(const MIRModule & mod,Opcode o,TyIdx idx)3938     IcallNode(const MIRModule &mod, Opcode o, TyIdx idx) : IcallNode(mod.GetCurFuncCodeMPAllocator(), o, idx) {}
3939 
IcallNode(MapleAllocator & allocator,const IcallNode & node)3940     IcallNode(MapleAllocator &allocator, const IcallNode &node)
3941         : NaryStmtNode(allocator, node),
3942           DeoptBundleInfo(allocator),
3943           retTyIdx(node.retTyIdx),
3944           returnValues(allocator.Adapter())
3945     {
3946     }
3947 
IcallNode(const MIRModule & mod,const IcallNode & node)3948     IcallNode(const MIRModule &mod, const IcallNode &node) : IcallNode(mod.GetCurFuncCodeMPAllocator(), node) {}
3949 
3950     IcallNode(IcallNode &node) = delete;
3951     IcallNode &operator=(const IcallNode &node) = delete;
3952     virtual ~IcallNode() = default;
3953 
3954     virtual void Dump(int32 indent, bool newline) const;
3955     bool Verify() const override;
3956     MIRType *GetCallReturnType() override;
3957     const MIRSymbol *GetCallReturnSymbol(const MIRModule &mod) const;
CloneTree(MapleAllocator & allocator)3958     IcallNode *CloneTree(MapleAllocator &allocator) const override
3959     {
3960         auto *node = allocator.GetMemPool()->New<IcallNode>(allocator, *this);
3961         for (size_t i = 0; i < GetNopndSize(); ++i) {
3962             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
3963         }
3964         for (size_t i = 0; i < returnValues.size(); ++i) {
3965             node->returnValues.push_back(returnValues[i]);
3966         }
3967         node->SetNumOpnds(GetNopndSize());
3968         for (const auto &elem : GetDeoptBundleInfo()) {
3969             node->AddDeoptBundleInfo(elem.first, elem.second);
3970         }
3971         return node;
3972     }
3973 
GetRetTyIdx()3974     TyIdx GetRetTyIdx() const
3975     {
3976         return retTyIdx;
3977     }
3978 
SetRetTyIdx(TyIdx idx)3979     void SetRetTyIdx(TyIdx idx)
3980     {
3981         retTyIdx = idx;
3982     }
3983 
GetReturnVec()3984     const CallReturnVector &GetReturnVec() const
3985     {
3986         return returnValues;
3987     }
3988 
GetReturnVec()3989     CallReturnVector &GetReturnVec()
3990     {
3991         return returnValues;
3992     }
3993 
SetReturnVec(const CallReturnVector & vec)3994     void SetReturnVec(const CallReturnVector &vec)
3995     {
3996         returnValues = vec;
3997     }
3998 
NumOpnds()3999     size_t NumOpnds() const override
4000     {
4001         DEBUG_ASSERT(numOpnds == GetNopndSize(), "IcallNode has wrong numOpnds field");
4002         return GetNopndSize();
4003     }
4004 
Dump(int32 indent)4005     void Dump(int32 indent) const override
4006     {
4007         Dump(indent, true);
4008     }
4009 
GetCallReturnVector()4010     CallReturnVector *GetCallReturnVector() override
4011     {
4012         return &returnValues;
4013     }
4014 
4015 private:
4016     TyIdx retTyIdx;  // for icall: return type for callee; for icallproto: the prototye
4017     // the 0th operand is the function pointer
4018     CallReturnVector returnValues;
4019 };
4020 
4021 // used by intrinsiccall and xintrinsiccall
4022 class IntrinsiccallNode : public NaryStmtNode, public DeoptBundleInfo {
4023 public:
IntrinsiccallNode(MapleAllocator & allocator,Opcode o)4024     IntrinsiccallNode(MapleAllocator &allocator, Opcode o)
4025         : NaryStmtNode(allocator, o),
4026           DeoptBundleInfo(allocator),
4027           intrinsic(INTRN_UNDEFINED),
4028           tyIdx(0),
4029           returnValues(allocator.Adapter())
4030     {
4031     }
4032 
IntrinsiccallNode(MapleAllocator & allocator,Opcode o,MIRIntrinsicID id)4033     IntrinsiccallNode(MapleAllocator &allocator, Opcode o, MIRIntrinsicID id)
4034         : NaryStmtNode(allocator, o),
4035           DeoptBundleInfo(allocator),
4036           intrinsic(id),
4037           tyIdx(0),
4038           returnValues(allocator.Adapter())
4039     {
4040     }
4041 
IntrinsiccallNode(const MIRModule & mod,Opcode o)4042     IntrinsiccallNode(const MIRModule &mod, Opcode o) : IntrinsiccallNode(mod.GetCurFuncCodeMPAllocator(), o) {}
4043 
IntrinsiccallNode(const MIRModule & mod,Opcode o,MIRIntrinsicID id)4044     IntrinsiccallNode(const MIRModule &mod, Opcode o, MIRIntrinsicID id)
4045         : IntrinsiccallNode(mod.GetCurFuncCodeMPAllocator(), o, id)
4046     {
4047     }
4048 
IntrinsiccallNode(MapleAllocator & allocator,const IntrinsiccallNode & node)4049     IntrinsiccallNode(MapleAllocator &allocator, const IntrinsiccallNode &node)
4050         : NaryStmtNode(allocator, node),
4051           DeoptBundleInfo(allocator),
4052           intrinsic(node.GetIntrinsic()),
4053           tyIdx(node.tyIdx),
4054           returnValues(allocator.Adapter())
4055     {
4056     }
4057 
IntrinsiccallNode(const MIRModule & mod,const IntrinsiccallNode & node)4058     IntrinsiccallNode(const MIRModule &mod, const IntrinsiccallNode &node)
4059         : IntrinsiccallNode(mod.GetCurFuncCodeMPAllocator(), node)
4060     {
4061     }
4062 
4063     IntrinsiccallNode(IntrinsiccallNode &node) = delete;
4064     IntrinsiccallNode &operator=(const IntrinsiccallNode &node) = delete;
4065     virtual ~IntrinsiccallNode() = default;
4066 
4067     virtual void Dump(int32 indent, bool newline) const;
4068     bool Verify() const override;
4069     MIRType *GetCallReturnType() override;
4070 
CloneTree(MapleAllocator & allocator)4071     IntrinsiccallNode *CloneTree(MapleAllocator &allocator) const override
4072     {
4073         auto *node = allocator.GetMemPool()->New<IntrinsiccallNode>(allocator, *this);
4074         for (size_t i = 0; i < GetNopndSize(); ++i) {
4075             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
4076         }
4077         for (size_t i = 0; i < returnValues.size(); ++i) {
4078             node->GetReturnVec().push_back(returnValues[i]);
4079         }
4080         node->SetNumOpnds(GetNopndSize());
4081         return node;
4082     }
4083 
GetIntrinsic()4084     MIRIntrinsicID GetIntrinsic() const
4085     {
4086         return intrinsic;
4087     }
4088 
SetIntrinsic(MIRIntrinsicID id)4089     void SetIntrinsic(MIRIntrinsicID id)
4090     {
4091         intrinsic = id;
4092     }
4093 
GetTyIdx()4094     TyIdx GetTyIdx() const
4095     {
4096         return tyIdx;
4097     }
4098 
SetTyIdx(TyIdx idx)4099     void SetTyIdx(TyIdx idx)
4100     {
4101         tyIdx = idx;
4102     }
4103 
GetReturnVec()4104     CallReturnVector &GetReturnVec()
4105     {
4106         return returnValues;
4107     }
4108 
GetReturnVec()4109     const CallReturnVector &GetReturnVec() const
4110     {
4111         return returnValues;
4112     }
4113 
SetReturnVec(const CallReturnVector & vec)4114     void SetReturnVec(const CallReturnVector &vec)
4115     {
4116         returnValues = vec;
4117     }
4118 
NumOpnds()4119     size_t NumOpnds() const override
4120     {
4121         DEBUG_ASSERT(numOpnds == GetNopndSize(), "IntrinsiccallNode has wrong numOpnds field");
4122         return GetNopndSize();
4123     }
4124 
Dump(int32 indent)4125     void Dump(int32 indent) const override
4126     {
4127         Dump(indent, true);
4128     }
4129 
GetCallReturnVector()4130     CallReturnVector *GetCallReturnVector() override
4131     {
4132         return &returnValues;
4133     }
4134 
GetCallReturnPair(uint32 i)4135     CallReturnPair &GetCallReturnPair(uint32 i)
4136     {
4137         DEBUG_ASSERT(i < returnValues.size(), "array index out of range");
4138         return returnValues.at(i);
4139     }
4140 
4141 private:
4142     MIRIntrinsicID intrinsic;
4143     TyIdx tyIdx;
4144     CallReturnVector returnValues;
4145 };
4146 
4147 // used by callinstant, virtualcallinstant, superclasscallinstant and
4148 // interfacecallinstant, callinstantassigned, virtualcallinstantassigned,
4149 // superclasscallinstantassigned and interfacecallinstantassigned
4150 class CallinstantNode : public CallNode {
4151 public:
CallinstantNode(MapleAllocator & allocator,Opcode o,TyIdx tIdx)4152     CallinstantNode(MapleAllocator &allocator, Opcode o, TyIdx tIdx) : CallNode(allocator, o), instVecTyIdx(tIdx) {}
4153 
CallinstantNode(const MIRModule & mod,Opcode o,TyIdx tIdx)4154     CallinstantNode(const MIRModule &mod, Opcode o, TyIdx tIdx)
4155         : CallinstantNode(mod.GetCurFuncCodeMPAllocator(), o, tIdx)
4156     {
4157     }
4158 
CallinstantNode(MapleAllocator & allocator,const CallinstantNode & node)4159     CallinstantNode(MapleAllocator &allocator, const CallinstantNode &node)
4160         : CallNode(allocator, node), instVecTyIdx(node.instVecTyIdx)
4161     {
4162     }
4163 
CallinstantNode(const MIRModule & mod,const CallinstantNode & node)4164     CallinstantNode(const MIRModule &mod, const CallinstantNode &node)
4165         : CallinstantNode(mod.GetCurFuncCodeMPAllocator(), node)
4166     {
4167     }
4168 
4169     CallinstantNode(CallinstantNode &node) = delete;
4170     CallinstantNode &operator=(const CallinstantNode &node) = delete;
4171     virtual ~CallinstantNode() = default;
4172 
4173     void Dump(int32 indent, bool newline) const override;
Dump(int32 indent)4174     void Dump(int32 indent) const override
4175     {
4176         Dump(indent, true);
4177     }
4178 
CloneTree(MapleAllocator & allocator)4179     CallinstantNode *CloneTree(MapleAllocator &allocator) const override
4180     {
4181         auto *node = allocator.GetMemPool()->New<CallinstantNode>(allocator, *this);
4182         for (size_t i = 0; i < GetNopndSize(); ++i) {
4183             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
4184         }
4185         for (size_t i = 0; i < GetReturnVec().size(); ++i) {
4186             node->GetReturnVec().push_back(GetNthReturnVec(i));
4187         }
4188         node->SetNumOpnds(GetNopndSize());
4189         return node;
4190     }
4191 
GetCallReturnVector()4192     CallReturnVector *GetCallReturnVector() override
4193     {
4194         return &GetReturnVec();
4195     }
4196 
4197 private:
4198     TyIdx instVecTyIdx;
4199 };
4200 
4201 class LabelNode : public StmtNode {
4202 public:
LabelNode()4203     LabelNode() : StmtNode(OP_label) {}
4204 
LabelNode(LabelIdx idx)4205     explicit LabelNode(LabelIdx idx) : StmtNode(OP_label), labelIdx(idx) {}
4206 
4207     virtual ~LabelNode() = default;
4208 
4209     void Dump(int32 indent) const override;
4210 
CloneTree(MapleAllocator & allocator)4211     LabelNode *CloneTree(MapleAllocator &allocator) const override
4212     {
4213         auto *l = allocator.GetMemPool()->New<LabelNode>(*this);
4214         l->SetStmtID(stmtIDNext++);
4215         return l;
4216     }
4217 
GetLabelIdx()4218     LabelIdx GetLabelIdx() const
4219     {
4220         return labelIdx;
4221     }
4222 
SetLabelIdx(LabelIdx idx)4223     void SetLabelIdx(LabelIdx idx)
4224     {
4225         labelIdx = idx;
4226     }
4227 
4228 private:
4229     LabelIdx labelIdx = 0;
4230 };
4231 
4232 class CommentNode : public StmtNode {
4233 public:
CommentNode(const MapleAllocator & allocator)4234     explicit CommentNode(const MapleAllocator &allocator) : StmtNode(OP_comment), comment(allocator.GetMemPool()) {}
4235 
CommentNode(const MIRModule & mod)4236     explicit CommentNode(const MIRModule &mod) : CommentNode(mod.GetCurFuncCodeMPAllocator()) {}
4237 
CommentNode(const MapleAllocator & allocator,const std::string & cmt)4238     CommentNode(const MapleAllocator &allocator, const std::string &cmt)
4239         : StmtNode(OP_comment), comment(cmt, allocator.GetMemPool())
4240     {
4241     }
4242 
CommentNode(const MIRModule & mod,const std::string & cmt)4243     CommentNode(const MIRModule &mod, const std::string &cmt) : CommentNode(mod.GetCurFuncCodeMPAllocator(), cmt) {}
4244 
CommentNode(const MapleAllocator & allocator,const CommentNode & node)4245     CommentNode(const MapleAllocator &allocator, const CommentNode &node)
4246         : StmtNode(node.GetOpCode(), node.GetPrimType()), comment(node.comment, allocator.GetMemPool())
4247     {
4248     }
4249 
CommentNode(const MIRModule & mod,const CommentNode & node)4250     CommentNode(const MIRModule &mod, const CommentNode &node) : CommentNode(mod.GetCurFuncCodeMPAllocator(), node) {}
4251 
4252     CommentNode(CommentNode &node) = delete;
4253     CommentNode &operator=(const CommentNode &node) = delete;
4254     virtual ~CommentNode() = default;
4255 
4256     void Dump(int32 indent) const override;
4257 
CloneTree(MapleAllocator & allocator)4258     CommentNode *CloneTree(MapleAllocator &allocator) const override
4259     {
4260         auto *c = allocator.GetMemPool()->New<CommentNode>(allocator, *this);
4261         return c;
4262     }
4263 
GetComment()4264     const MapleString &GetComment() const
4265     {
4266         return comment;
4267     }
4268 
SetComment(MapleString com)4269     void SetComment(MapleString com)
4270     {
4271         comment = com;
4272     }
4273 
SetComment(const std::string & str)4274     void SetComment(const std::string &str)
4275     {
4276         comment = str;
4277     }
4278 
SetComment(const char * str)4279     void SetComment(const char *str)
4280     {
4281         comment = str;
4282     }
4283 
Append(const std::string & str)4284     void Append(const std::string &str)
4285     {
4286         comment += str;
4287     }
4288 
4289 private:
4290     MapleString comment;
4291 };
4292 
4293 enum AsmQualifierKind : unsigned {  // they are alreadgy Maple IR keywords
4294     kASMvolatile,
4295     kASMinline,
4296     kASMgoto,
4297 };
4298 
4299 class AsmNode : public NaryStmtNode {
4300 public:
AsmNode(MapleAllocator * alloc)4301     explicit AsmNode(MapleAllocator *alloc)
4302         : NaryStmtNode(*alloc, OP_asm),
4303           asmString(alloc->GetMemPool()),
4304           inputConstraints(alloc->Adapter()),
4305           asmOutputs(alloc->Adapter()),
4306           outputConstraints(alloc->Adapter()),
4307           clobberList(alloc->Adapter()),
4308           gotoLabels(alloc->Adapter()),
4309           qualifiers(0)
4310     {
4311     }
4312 
AsmNode(MapleAllocator & allocator,const AsmNode & node)4313     AsmNode(MapleAllocator &allocator, const AsmNode &node)
4314         : NaryStmtNode(allocator, node),
4315           asmString(node.asmString, allocator.GetMemPool()),
4316           inputConstraints(allocator.Adapter()),
4317           asmOutputs(allocator.Adapter()),
4318           outputConstraints(allocator.Adapter()),
4319           clobberList(allocator.Adapter()),
4320           gotoLabels(allocator.Adapter()),
4321           qualifiers(node.qualifiers)
4322     {
4323     }
4324 
4325     virtual ~AsmNode() = default;
4326 
4327     AsmNode *CloneTree(MapleAllocator &allocator) const override;
4328 
SetQualifier(AsmQualifierKind x)4329     void SetQualifier(AsmQualifierKind x)
4330     {
4331         qualifiers |= (1U << static_cast<uint32>(x));
4332     }
4333 
GetQualifier(AsmQualifierKind x)4334     bool GetQualifier(AsmQualifierKind x) const
4335     {
4336         return (qualifiers & (1U << static_cast<uint32>(x))) != 0;
4337     }
4338 
GetCallReturnVector()4339     CallReturnVector *GetCallReturnVector() override
4340     {
4341         return &asmOutputs;
4342     }
4343 
SetHasWriteInputs()4344     void SetHasWriteInputs()
4345     {
4346         hasWriteInputs = true;
4347     }
4348 
HasWriteInputs()4349     bool HasWriteInputs() const
4350     {
4351         return hasWriteInputs;
4352     }
4353 
4354     void DumpOutputs(int32 indent, std::string &uStr) const;
4355     void DumpInputOperands(int32 indent, std::string &uStr) const;
4356     void Dump(int32 indent) const override;
4357 
4358     MapleString asmString;
4359     MapleVector<UStrIdx> inputConstraints;  // length is numOpnds
4360     CallReturnVector asmOutputs;
4361     MapleVector<UStrIdx> outputConstraints;  // length is returnValues.size()
4362     MapleVector<UStrIdx> clobberList;
4363     MapleVector<LabelIdx> gotoLabels;
4364     uint32 qualifiers;
4365 
4366 private:
4367     bool hasWriteInputs = false;
4368 };
4369 
4370 void DumpCallReturns(const MIRModule &mod, CallReturnVector nrets, int32 indent);
4371 bool HasIreadExpr(const BaseNode *expr);
4372 size_t MaxDepth(const BaseNode *expr);
4373 }  // namespace maple
4374 
4375 #define LOAD_SAFE_CAST_FOR_MIR_NODE
4376 #include "ir_safe_cast_traits.def"
4377 
4378 #endif  // MAPLE_IR_INCLUDE_MIR_NODES_H
4379