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