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 
40 #ifdef ARK_LITECG_DEBUG
41 extern void EmitStr(const MapleString &mplStr);
42 #endif
43 
44 class MIRPregTable;  // circular dependency exists, no other choice
45 class TypeTable;     // circular dependency exists, no other choice
46 
47 struct RegFieldPair {
48 public:
49     RegFieldPair() = default;
50 
RegFieldPairmaple::RegFieldPair51     RegFieldPair(FieldID fidx, PregIdx pidx) : fieldID(fidx), pregIdx(pidx) {}
52 
IsRegmaple::RegFieldPair53     bool IsReg() const
54     {
55         return pregIdx > 0;
56     }
57 
GetFieldIDmaple::RegFieldPair58     FieldID GetFieldID() const
59     {
60         return fieldID;
61     }
62 
GetPregIdxmaple::RegFieldPair63     PregIdx GetPregIdx() const
64     {
65         return pregIdx;
66     }
67 
SetFieldIDmaple::RegFieldPair68     void SetFieldID(FieldID fld)
69     {
70         fieldID = fld;
71     }
72 
SetPregIdxmaple::RegFieldPair73     void SetPregIdx(PregIdx idx)
74     {
75         pregIdx = idx;
76     }
77 
78 private:
79     FieldID fieldID = 0;
80     PregIdx pregIdx = 0;
81 };
82 
83 using CallReturnPair = std::pair<StIdx, RegFieldPair>;
84 using CallReturnVector = MapleVector<CallReturnPair>;
85 // Made public so that other modules (such as maplebe) can print intrinsic names
86 // in debug information or comments in assembly files.
87 const char *GetIntrinsicName(MIRIntrinsicID intrn);
88 class BaseNode : public BaseNodeT {
89 public:
BaseNode(Opcode o)90     explicit BaseNode(Opcode o)
91     {
92         op = o;
93         ptyp = kPtyInvalid;
94         typeFlag = 0;
95         numOpnds = 0;
96     }
97 
BaseNode(Opcode o, uint8 numOpr)98     BaseNode(Opcode o, uint8 numOpr)
99     {
100         op = o;
101         ptyp = kPtyInvalid;
102         typeFlag = 0;
103         numOpnds = numOpr;
104     }
105 
BaseNode(const Opcode o, const PrimType typ, uint8 numOpr)106     BaseNode(const Opcode o, const PrimType typ, uint8 numOpr)
107     {
108         op = o;
109         ptyp = typ;
110         typeFlag = 0;
111         numOpnds = numOpr;
112     }
113 
114     virtual ~BaseNode() = default;
115 
CloneTree(MapleAllocator &allocator) const116     virtual BaseNode *CloneTree(MapleAllocator &allocator) const
117     {
118         return allocator.GetMemPool()->New<BaseNode>(*this);
119     }
120 
121 #ifdef ARK_LITECG_DEBUG
122     virtual void DumpBase(int32 indent) const;
123 
Dump(int32 indent) const124     virtual void Dump(int32 indent) const
125     {
126         DumpBase(indent);
127     }
128 
Dump() const129     void Dump() const
130     {
131         Dump(0);
132         LogInfo::MapleLogger() << '\n';
133     }
134 #endif
135 
SizeOfInstr() const136     virtual uint8 SizeOfInstr() const
137     {
138         return kOpcodeInfo.GetTableItemAt(GetOpCode()).instrucSize;
139     }
140 
NumOpnds() const141     virtual size_t NumOpnds() const
142     {
143         return numOpnds;
144     }
145 
Opnd(size_t) const146     virtual BaseNode *Opnd(size_t) const
147     {
148         DEBUG_ASSERT(0, "override needed");
149         return nullptr;
150     }
151 
SetOpnd(BaseNode *, size_t)152     virtual void SetOpnd(BaseNode *, size_t)
153     {
154         DEBUG_ASSERT(0, "This should not happen");
155     }
156 
IsLeaf() const157     virtual bool IsLeaf() const
158     {
159         return true;
160     }
161 
GetCallReturnVector()162     virtual CallReturnVector *GetCallReturnVector()
163     {
164         return nullptr;
165     }
166 
GetCallReturnType()167     virtual MIRType *GetCallReturnType()
168     {
169         return nullptr;
170     }
171 
IsUnaryNode() const172     virtual bool IsUnaryNode() const
173     {
174         return false;
175     }
176 
IsBinaryNode() const177     virtual bool IsBinaryNode() const
178     {
179         return false;
180     }
181 
IsNaryNode() const182     virtual bool IsNaryNode() const
183     {
184         return false;
185     }
186 
IsCondBr() const187     bool IsCondBr() const
188     {
189         return kOpcodeInfo.IsCondBr(GetOpCode());
190     }
191 
IsConstval() const192     bool IsConstval() const
193     {
194         return op == OP_constval;
195     }
196 
IsSSANode() const197     virtual bool IsSSANode() const
198     {
199         return false;
200     }
201 
SetDebugComment(const MapleString* str)202     void SetDebugComment(const MapleString* str)
203     {
204         debugComment = str;
205     }
206 
GetDebugComment() const207     const MapleString* GetDebugComment() const
208     {
209         return debugComment;
210     }
211 
212 private:
213     const MapleString* debugComment {nullptr};
214 };
215 
216 class UnaryNode : public BaseNode {
217 public:
UnaryNode(Opcode o)218     explicit UnaryNode(Opcode o) : BaseNode(o, 1) {}
219 
UnaryNode(Opcode o, PrimType typ)220     UnaryNode(Opcode o, PrimType typ) : BaseNode(o, typ, 1) {}
221 
UnaryNode(Opcode o, PrimType typ, BaseNode *expr)222     UnaryNode(Opcode o, PrimType typ, BaseNode *expr) : BaseNode(o, typ, 1), uOpnd(expr) {}
223 
224     virtual ~UnaryNode() override = default;
225 
226 #ifdef ARK_LITECG_DEBUG
227     void DumpOpnd(const MIRModule &mod, int32 indent) const;
228     void DumpOpnd(int32 indent) const;
229     void Dump(int32 indent) const override;
230 #endif
231 
232     UnaryNode *CloneTree(MapleAllocator &allocator) const override
233     {
234         auto *node = allocator.GetMemPool()->New<UnaryNode>(*this);
235         node->SetOpnd(uOpnd->CloneTree(allocator), 0);
236         return node;
237     }
238 
239     BaseNode *Opnd(size_t) const override
240     {
241         return uOpnd;
242     }
243 
244     size_t NumOpnds() const override
245     {
246         return 1;
247     }
248 
249     void SetOpnd(BaseNode *node, size_t) override
250     {
251         uOpnd = node;
252     }
253 
254     bool IsLeaf() const override
255     {
256         return false;
257     }
258 
259     bool IsUnaryNode() const override
260     {
261         return true;
262     }
263 
264 private:
265     BaseNode *uOpnd = nullptr;
266 };
267 
268 class TypeCvtNode : public UnaryNode {
269 public:
TypeCvtNode(Opcode o)270     explicit TypeCvtNode(Opcode o) : UnaryNode(o) {}
271 
TypeCvtNode(Opcode o, PrimType typ)272     TypeCvtNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
273 
TypeCvtNode(Opcode o, PrimType typ, PrimType fromtyp, BaseNode *expr)274     TypeCvtNode(Opcode o, PrimType typ, PrimType fromtyp, BaseNode *expr)
275         : UnaryNode(o, typ, expr), fromPrimType(fromtyp)
276     {
277     }
278 
279     virtual ~TypeCvtNode() = default;
280 
281 #ifdef ARK_LITECG_DEBUG
282     void Dump(int32 indent) const override;
283 #endif
284 
285     TypeCvtNode *CloneTree(MapleAllocator &allocator) const override
286     {
287         auto *node = allocator.GetMemPool()->New<TypeCvtNode>(*this);
288         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
289         return node;
290     }
291 
FromType() const292     PrimType FromType() const
293     {
294         return fromPrimType;
295     }
296 
SetFromType(PrimType from)297     void SetFromType(PrimType from)
298     {
299         fromPrimType = from;
300     }
301 
302 private:
303     PrimType fromPrimType = kPtyInvalid;
304 };
305 
306 // used for retype
307 class RetypeNode : public TypeCvtNode {
308 public:
RetypeNode()309     RetypeNode() : TypeCvtNode(OP_retype) {}
310 
RetypeNode(PrimType typ)311     explicit RetypeNode(PrimType typ) : TypeCvtNode(OP_retype, typ) {}
312 
RetypeNode(PrimType typ, PrimType fromtyp, TyIdx idx, BaseNode *expr)313     RetypeNode(PrimType typ, PrimType fromtyp, TyIdx idx, BaseNode *expr)
314         : TypeCvtNode(OP_retype, typ, fromtyp, expr), tyIdx(idx)
315     {
316         DEBUG_ASSERT(GetPrimTypeSize(fromtyp) == GetPrimTypeSize(typ), "retype bit widith doesn' match");
317     }
318 
319     virtual ~RetypeNode() = default;
320 
321 #ifdef ARK_LITECG_DEBUG
322     void Dump(int32 indent) const override;
323 #endif
324 
325     RetypeNode *CloneTree(MapleAllocator &allocator) const override
326     {
327         auto *node = allocator.GetMemPool()->New<RetypeNode>(*this);
328         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
329         return node;
330     }
331 
GetTyIdx() const332     const TyIdx &GetTyIdx() const
333     {
334         return tyIdx;
335     }
336 
SetTyIdx(const TyIdx tyIdxVal)337     void SetTyIdx(const TyIdx tyIdxVal)
338     {
339         tyIdx = tyIdxVal;
340     }
341 
342 private:
343     TyIdx tyIdx = TyIdx(0);
344 };
345 
346 // used for extractbits, sext, zext
347 class ExtractbitsNode : public UnaryNode {
348 public:
ExtractbitsNode(Opcode o)349     explicit ExtractbitsNode(Opcode o) : UnaryNode(o) {}
350 
ExtractbitsNode(Opcode o, PrimType typ)351     ExtractbitsNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
352 
ExtractbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size)353     ExtractbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size)
354         : UnaryNode(o, typ), bitsOffset(offset), bitsSize(size)
355     {
356     }
357 
ExtractbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size, BaseNode *expr)358     ExtractbitsNode(Opcode o, PrimType typ, uint8 offset, uint8 size, BaseNode *expr)
359         : UnaryNode(o, typ, expr), bitsOffset(offset), bitsSize(size)
360     {
361     }
362 
363     virtual ~ExtractbitsNode() = default;
364 
365 #ifdef ARK_LITECG_DEBUG
366     void Dump(int32 indent) const override;
367 #endif
368 
369     ExtractbitsNode *CloneTree(MapleAllocator &allocator) const override
370     {
371         auto *node = allocator.GetMemPool()->New<ExtractbitsNode>(*this);
372         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
373         return node;
374     }
375 
GetBitsOffset() const376     uint8 GetBitsOffset() const
377     {
378         return bitsOffset;
379     }
380 
SetBitsOffset(uint8 offset)381     void SetBitsOffset(uint8 offset)
382     {
383         bitsOffset = offset;
384     }
385 
GetBitsSize() const386     uint8 GetBitsSize() const
387     {
388         return bitsSize;
389     }
390 
SetBitsSize(uint8 size)391     void SetBitsSize(uint8 size)
392     {
393         bitsSize = size;
394     }
395 
396 private:
397     uint8 bitsOffset = 0;
398     uint8 bitsSize = 0;
399 };
400 
401 // iaddrof also use this node
402 class IreadNode : public UnaryNode {
403 public:
IreadNode(Opcode o)404     explicit IreadNode(Opcode o) : UnaryNode(o) {}
405 
IreadNode(Opcode o, PrimType typ)406     IreadNode(Opcode o, PrimType typ) : UnaryNode(o, typ) {}
407 
IreadNode(Opcode o, PrimType typ, TyIdx typeIdx, FieldID fid)408     IreadNode(Opcode o, PrimType typ, TyIdx typeIdx, FieldID fid) : UnaryNode(o, typ), tyIdx(typeIdx), fieldID(fid) {}
409 
IreadNode(Opcode o, PrimType typ, TyIdx typeIdx, FieldID fid, BaseNode *expr)410     IreadNode(Opcode o, PrimType typ, TyIdx typeIdx, FieldID fid, BaseNode *expr)
411         : UnaryNode(o, typ, expr), tyIdx(typeIdx), fieldID(fid)
412     {
413     }
414 
415     virtual ~IreadNode() = default;
416 
417 #ifdef ARK_LITECG_DEBUG
418     void Dump(int32 indent) const override;
419 #endif
420 
421     IreadNode *CloneTree(MapleAllocator &allocator) const override
422     {
423         auto *node = allocator.GetMemPool()->New<IreadNode>(*this);
424         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
425         return node;
426     }
427 
GetTyIdx() const428     const TyIdx &GetTyIdx() const
429     {
430         return tyIdx;
431     }
432 
SetTyIdx(const TyIdx tyIdxVal)433     void SetTyIdx(const TyIdx tyIdxVal)
434     {
435         tyIdx = tyIdxVal;
436     }
437 
GetFieldID() const438     FieldID GetFieldID() const
439     {
440         return fieldID;
441     }
442 
SetFieldID(FieldID fieldIDVal)443     void SetFieldID(FieldID fieldIDVal)
444     {
445         fieldID = fieldIDVal;
446     }
447 
448     // the base of an address expr is either a leaf or an iread
GetAddrExprBase() const449     BaseNode &GetAddrExprBase() const
450     {
451         BaseNode *base = Opnd(0);
452         while (base->NumOpnds() != 0 && base->GetOpCode() != OP_iread) {
453             base = base->Opnd(0);
454         }
455         return *base;
456     }
457 
458     MIRType *GetType() const;
459 
460 protected:
461     TyIdx tyIdx = TyIdx(0);
462     FieldID fieldID = 0;
463 };
464 
465 // IaddrofNode has the same member fields and member methods as IreadNode
466 using IaddrofNode = IreadNode;
467 
468 class BinaryOpnds {
469 public:
470     virtual ~BinaryOpnds() = default;
471 
472 #ifdef ARK_LITECG_DEBUG
473     virtual void Dump(int32 indent) const;
474 #endif
475 
GetBOpnd(size_t i) const476     BaseNode *GetBOpnd(size_t i) const
477     {
478         CHECK_FATAL(i < kOperandNumBinary, "Invalid operand idx in BinaryOpnds");
479         return bOpnd[i];
480     }
481 
482     void SetBOpnd(BaseNode *node, size_t i)
483     {
484         CHECK_FATAL(i < kOperandNumBinary, "Invalid operand idx in BinaryOpnds");
485         bOpnd[i] = node;
486     }
487 
488 private:
489     BaseNode *bOpnd[kOperandNumBinary];
490 };
491 
492 class BinaryNode : public BaseNode, public BinaryOpnds {
493 public:
494     explicit BinaryNode(Opcode o) : BaseNode(o, kOperandNumBinary) {}
495 
496     BinaryNode(Opcode o, PrimType typ) : BaseNode(o, typ, kOperandNumBinary) {}
497 
498     BinaryNode(Opcode o, PrimType typ, BaseNode *l, BaseNode *r) : BaseNode(o, typ, kOperandNumBinary)
499     {
500         SetBOpnd(l, 0);
501         SetBOpnd(r, 1);
502     }
503 
504     virtual ~BinaryNode() = default;
505 
506 #ifdef ARK_LITECG_DEBUG
507     using BaseNode::Dump;
508     void Dump(int32 indent) const override;
509 #endif
510 
511     BinaryNode *CloneTree(MapleAllocator &allocator) const override
512     {
513         auto *node = allocator.GetMemPool()->New<BinaryNode>(*this);
514         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
515         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
516         return node;
517     }
518 
IsCommutative() const519     bool IsCommutative() const
520     {
521         switch (GetOpCode()) {
522             case OP_add:
523             case OP_mul:
524             case OP_band:
525             case OP_bior:
526             case OP_bxor:
527                 return true;
528             default:
529                 return false;
530         }
531     }
532 
533     BaseNode *Opnd(size_t i) const override
534     {
535         DEBUG_ASSERT(i < kOperandNumBinary, "invalid operand idx in BinaryNode");
536         DEBUG_ASSERT(i >= 0, "invalid operand idx in BinaryNode");
537         return GetBOpnd(i);
538     }
539 
540     size_t NumOpnds() const override
541     {
542         return kOperandNumBinary;
543     }
544 
545     void SetOpnd(BaseNode *node, size_t i = 0) override
546     {
547         SetBOpnd(node, i);
548     }
549 
550     bool IsLeaf() const override
551     {
552         return false;
553     }
554 
555     bool IsBinaryNode() const override
556     {
557         return true;
558     }
559 };
560 
561 class CompareNode : public BinaryNode {
562 public:
CompareNode(Opcode o)563     explicit CompareNode(Opcode o) : BinaryNode(o) {}
564 
CompareNode(Opcode o, PrimType typ)565     CompareNode(Opcode o, PrimType typ) : BinaryNode(o, typ) {}
566 
CompareNode(Opcode o, PrimType typ, PrimType otype, BaseNode *l, BaseNode *r)567     CompareNode(Opcode o, PrimType typ, PrimType otype, BaseNode *l, BaseNode *r)
568         : BinaryNode(o, typ, l, r), opndType(otype)
569     {
570     }
571 
572     virtual ~CompareNode() = default;
573 
574 #ifdef ARK_LITECG_DEBUG
575     using BinaryNode::Dump;
576     void Dump(int32 indent) const override;
577 #endif
578 
579     CompareNode *CloneTree(MapleAllocator &allocator) const override
580     {
581         auto *node = allocator.GetMemPool()->New<CompareNode>(*this);
582         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
583         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
584         return node;
585     }
586 
GetOpndType() const587     PrimType GetOpndType() const
588     {
589         return opndType;
590     }
591 
SetOpndType(PrimType type)592     void SetOpndType(PrimType type)
593     {
594         opndType = type;
595     }
596 
597 private:
598     PrimType opndType = kPtyInvalid;  // type of operands.
599 };
600 
601 class NaryOpnds {
602 public:
NaryOpnds(MapleAllocator &mpallocter)603     explicit NaryOpnds(MapleAllocator &mpallocter) : nOpnd(mpallocter.Adapter()) {}
604 
605     virtual ~NaryOpnds() = default;
606 
607 #ifdef ARK_LITECG_DEBUG
608     virtual void Dump(int32 indent) const;
609 #endif
610 
GetNopnd() const611     const MapleVector<BaseNode *> &GetNopnd() const
612     {
613         return nOpnd;
614     }
615 
GetNopnd()616     MapleVector<BaseNode *> &GetNopnd()
617     {
618         return nOpnd;
619     }
620 
GetNopndSize() const621     size_t GetNopndSize() const
622     {
623         return nOpnd.size();
624     }
625 
GetNopndAt(size_t i) const626     BaseNode *GetNopndAt(size_t i) const
627     {
628         CHECK_FATAL(i < nOpnd.size(), "array index out of range");
629         return nOpnd[i];
630     }
631 
632     void SetNOpndAt(size_t i, BaseNode *opnd)
633     {
634         CHECK_FATAL(i < nOpnd.size(), "array index out of range");
635         nOpnd[i] = opnd;
636     }
637 
638     void SetNOpnd(const MapleVector<BaseNode *> &val)
639     {
640         nOpnd = val;
641     }
642 
643 private:
644     MapleVector<BaseNode *> nOpnd;
645 };
646 
647 class MapleValue {
648 public:
649     MapleValue(PregIdx preg) : pregIdx(preg), kind(kPregKind) {}
650     MapleValue(MIRSymbol *sym) : symbol(sym), kind(kSymbolKind) {}
651     MapleValue(MIRConst *value) : constVal(value), kind(kConstKind) {}
652     MapleValue(const MapleValue &val) = default;
653     ~MapleValue() = default;
654 
655     enum MapleValueKind {
656         kPregKind,
657         kSymbolKind,
658         kConstKind,
659     };
660 
661     MapleValueKind GetMapleValueKind() const
662     {
663         return kind;
664     }
665 
666     const MIRSymbol &GetSymbol() const
667     {
668         DEBUG_ASSERT(symbol != nullptr, "value is not be initialized with symbol");
669         return *symbol;
670     }
671 
672     PregIdx GetPregIdx() const
673     {
674         DEBUG_ASSERT(kind == kPregKind, "value is not be initialized with preg");
675         return pregIdx;
676     }
677 
678     const MIRConst &GetConstValue() const
679     {
680         DEBUG_ASSERT(kind == kConstKind, "value is not be initialized with preg");
681         return *constVal;
682     }
683 
684 private:
685     PregIdx pregIdx = 0;
686     MIRSymbol *symbol = nullptr;
687     MIRConst *constVal = nullptr;
688     MapleValueKind kind;
689 };
690 
691 class DeoptBundleInfo {
692 public:
693     explicit DeoptBundleInfo(MapleAllocator &mpallocter) : deoptBundleInfo(mpallocter.Adapter()) {}
694 
695     virtual ~DeoptBundleInfo() = default;
696 
697 #ifdef ARK_LITECG_DEBUG
698     virtual void Dump(int32 indent) const;
699 #endif
700 
701     const MapleUnorderedMap<int32, MapleValue> &GetDeoptBundleInfo() const
702     {
703         return deoptBundleInfo;
704     }
705 
706     MapleUnorderedMap<int32, MapleValue> &GetDeoptBundleInfo()
707     {
708         return deoptBundleInfo;
709     }
710 
711     void SetDeoptBundleInfo(const MapleUnorderedMap<int32, MapleValue> &vregMap)
712     {
713         deoptBundleInfo = vregMap;
714     }
715 
716     void AddDeoptBundleInfo(int32 deoptVreg, MapleValue value)
717     {
718         deoptBundleInfo.insert(std::pair<int32, MapleValue>(deoptVreg, value));
719     }
720 
721 private:
722     MapleUnorderedMap<int32, MapleValue> deoptBundleInfo;
723 };
724 
725 class NaryNode : public BaseNode, public NaryOpnds {
726 public:
727     NaryNode(MapleAllocator &allocator, Opcode o) : BaseNode(o), NaryOpnds(allocator) {}
728 
729     NaryNode(const MIRModule &mod, Opcode o) : NaryNode(mod.GetCurFuncCodeMPAllocator(), o) {}
730 
731     NaryNode(MapleAllocator &allocator, Opcode o, PrimType typ) : BaseNode(o, typ, 0), NaryOpnds(allocator) {}
732 
733     NaryNode(const MIRModule &mod, Opcode o, PrimType typ) : NaryNode(mod.GetCurFuncCodeMPAllocator(), o, typ) {}
734 
735     NaryNode(MapleAllocator &allocator, const NaryNode &node)
736         : BaseNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds), NaryOpnds(allocator)
737     {
738     }
739 
740     NaryNode(const MIRModule &mod, const NaryNode &node) : NaryNode(mod.GetCurFuncCodeMPAllocator(), node) {}
741 
742     NaryNode(NaryNode &node) = delete;
743     NaryNode &operator=(const NaryNode &node) = delete;
744     virtual ~NaryNode() = default;
745 
746 #ifdef ARK_LITECG_DEBUG
747     void Dump(int32 indent) const override;
748 #endif
749 
750     NaryNode *CloneTree(MapleAllocator &allocator) const override
751     {
752         auto *node = allocator.GetMemPool()->New<NaryNode>(allocator, *this);
753         for (size_t i = 0; i < GetNopndSize(); ++i) {
754             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
755         }
756         return node;
757     }
758 
759     BaseNode *Opnd(size_t i) const override
760     {
761         return GetNopndAt(i);
762     }
763 
764     size_t NumOpnds() const override
765     {
766         DEBUG_ASSERT(numOpnds == GetNopndSize(), "NaryNode has wrong numOpnds field");
767         return GetNopndSize();
768     }
769 
770     void SetOpnd(BaseNode *node, size_t i = 0) override
771     {
772         DEBUG_ASSERT(i < GetNopnd().size(), "array index out of range");
773         SetNOpndAt(i, node);
774     }
775 
776     bool IsLeaf() const override
777     {
778         return false;
779     }
780 
781     bool IsNaryNode() const override
782     {
783         return true;
784     }
785 };
786 
787 class IntrinsicopNode : public NaryNode {
788 public:
789     IntrinsicopNode(MapleAllocator &allocator, Opcode o, TyIdx typeIdx = TyIdx())
790         : NaryNode(allocator, o), intrinsic(INTRN_UNDEFINED), tyIdx(typeIdx)
791     {
792     }
793 
794     IntrinsicopNode(const MIRModule &mod, Opcode o, TyIdx typeIdx = TyIdx())
795         : IntrinsicopNode(mod.GetCurFuncCodeMPAllocator(), o, typeIdx)
796     {
797     }
798 
799     IntrinsicopNode(MapleAllocator &allocator, Opcode o, PrimType typ, TyIdx typeIdx = TyIdx())
800         : NaryNode(allocator, o, typ), intrinsic(INTRN_UNDEFINED), tyIdx(typeIdx)
801     {
802     }
803 
804     IntrinsicopNode(const MIRModule &mod, Opcode o, PrimType typ, TyIdx typeIdx = TyIdx())
805         : IntrinsicopNode(mod.GetCurFuncCodeMPAllocator(), o, typ, typeIdx)
806     {
807     }
808 
809     IntrinsicopNode(MapleAllocator &allocator, const IntrinsicopNode &node)
810         : NaryNode(allocator, node), intrinsic(node.GetIntrinsic()), tyIdx(node.GetTyIdx())
811     {
812     }
813 
814     IntrinsicopNode(const MIRModule &mod, const IntrinsicopNode &node)
815         : IntrinsicopNode(mod.GetCurFuncCodeMPAllocator(), node)
816     {
817     }
818 
819     IntrinsicopNode(IntrinsicopNode &node) = delete;
820     IntrinsicopNode &operator=(const IntrinsicopNode &node) = delete;
821     virtual ~IntrinsicopNode() = default;
822 
823 #ifdef ARK_LITECG_DEBUG
824     void Dump(int32 indent) const override;
825 #endif
826 
827     IntrinsicopNode *CloneTree(MapleAllocator &allocator) const override
828     {
829         auto *node = allocator.GetMemPool()->New<IntrinsicopNode>(allocator, *this);
830         for (size_t i = 0; i < GetNopndSize(); ++i) {
831             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
832         }
833         node->SetNumOpnds(GetNopndSize());
834         return node;
835     }
836 
GetIntrinsic() const837     MIRIntrinsicID GetIntrinsic() const
838     {
839         return intrinsic;
840     }
841 
SetIntrinsic(MIRIntrinsicID intrinsicID)842     void SetIntrinsic(MIRIntrinsicID intrinsicID)
843     {
844         intrinsic = intrinsicID;
845     }
846 
GetTyIdx() const847     TyIdx GetTyIdx() const
848     {
849         return tyIdx;
850     }
851 
SetTyIdx(TyIdx idx)852     void SetTyIdx(TyIdx idx)
853     {
854         tyIdx = idx;
855     }
856 
857     // IntrinDesc query
GetIntrinDesc() const858     const IntrinDesc &GetIntrinDesc() const
859     {
860         return IntrinDesc::intrinTable[intrinsic];
861     }
862 
863 private:
864     MIRIntrinsicID intrinsic;
865     TyIdx tyIdx;
866 };
867 
868 class ConstvalNode : public BaseNode {
869 public:
ConstvalNode()870     ConstvalNode() : BaseNode(OP_constval) {}
871 
ConstvalNode(PrimType typ)872     explicit ConstvalNode(PrimType typ) : BaseNode(OP_constval, typ, 0) {}
873 
ConstvalNode(MIRConst *constv)874     explicit ConstvalNode(MIRConst *constv) : BaseNode(OP_constval), constVal(constv) {}
875 
ConstvalNode(PrimType typ, MIRConst *constv)876     ConstvalNode(PrimType typ, MIRConst *constv) : BaseNode(OP_constval, typ, 0), constVal(constv) {}
877     virtual ~ConstvalNode() = default;
878 
879 #ifdef ARK_LITECG_DEBUG
880     void Dump(int32 indent) const override;
881 #endif
882 
883     ConstvalNode *CloneTree(MapleAllocator &allocator) const override
884     {
885         return allocator.GetMemPool()->New<ConstvalNode>(*this);
886     }
887 
GetConstVal() const888     const MIRConst *GetConstVal() const
889     {
890         return constVal;
891     }
892 
GetConstVal()893     MIRConst *GetConstVal()
894     {
895         DEBUG_ASSERT(constVal != nullptr, "constVal shoule not be nullptr");
896         return constVal;
897     }
898 
SetConstVal(MIRConst *val)899     void SetConstVal(MIRConst *val)
900     {
901         constVal = val;
902     }
903 
904 private:
905     MIRConst *constVal = nullptr;
906 };
907 
908 class AddrofNode : public BaseNode {
909 public:
AddrofNode(Opcode o)910     explicit AddrofNode(Opcode o) : BaseNode(o), stIdx() {}
911 
AddrofNode(Opcode o, PrimType typ)912     AddrofNode(Opcode o, PrimType typ) : AddrofNode(o, typ, StIdx(), 0) {}
913 
AddrofNode(Opcode o, PrimType typ, StIdx sIdx, FieldID fid)914     AddrofNode(Opcode o, PrimType typ, StIdx sIdx, FieldID fid) : BaseNode(o, typ, 0), stIdx(sIdx), fieldID(fid) {}
915 
916     virtual ~AddrofNode() = default;
917 
918 #ifdef ARK_LITECG_DEBUG
919     void Dump(int32 indent) const override;
920 #endif
921 
922     AddrofNode *CloneTree(MapleAllocator &allocator) const override
923     {
924         return allocator.GetMemPool()->New<AddrofNode>(*this);
925     }
926 
GetStIdx() const927     StIdx GetStIdx() const
928     {
929         return stIdx;
930     }
931 
SetStIdx(StIdx idx)932     void SetStIdx(StIdx idx)
933     {
934         stIdx = idx;
935     }
936 
SetStFullIdx(uint32 idx)937     void SetStFullIdx(uint32 idx)
938     {
939         stIdx.SetFullIdx(idx);
940     }
941 
GetFieldID() const942     FieldID GetFieldID() const
943     {
944         return fieldID;
945     }
946 
SetFieldID(FieldID fieldIDVal)947     void SetFieldID(FieldID fieldIDVal)
948     {
949         fieldID = fieldIDVal;
950     }
951 
952 private:
953     StIdx stIdx;
954     FieldID fieldID = 0;
955 };
956 
957 // DreadNode has the same member fields and member methods as AddrofNode
958 using DreadNode = AddrofNode;
959 
960 class DreadoffNode : public BaseNode {
961 public:
DreadoffNode(Opcode o)962     explicit DreadoffNode(Opcode o) : BaseNode(o), stIdx() {}
963 
DreadoffNode(Opcode o, PrimType typ)964     DreadoffNode(Opcode o, PrimType typ) : BaseNode(o, typ, 0), stIdx() {}
965 
966     virtual ~DreadoffNode() = default;
967 
968 #ifdef ARK_LITECG_DEBUG
969     void Dump(int32 indent) const override;
970 #endif
971 
972     DreadoffNode *CloneTree(MapleAllocator &allocator) const override
973     {
974         return allocator.GetMemPool()->New<DreadoffNode>(*this);
975     }
976 
977 public:
978     StIdx stIdx;
979     int32 offset = 0;
980 };
981 
982 class RegreadNode : public BaseNode {
983 public:
RegreadNode()984     RegreadNode() : BaseNode(OP_regread) {}
985 
RegreadNode(PregIdx pIdx)986     explicit RegreadNode(PregIdx pIdx) : BaseNode(OP_regread), regIdx(pIdx) {}
987 
RegreadNode(PrimType primType, PregIdx pIdx)988     RegreadNode(PrimType primType, PregIdx pIdx) : RegreadNode(pIdx)
989     {
990         ptyp = primType;
991     }
992 
993     virtual ~RegreadNode() = default;
994 
995 #ifdef ARK_LITECG_DEBUG
996     void Dump(int32 indent) const override;
997 #endif
998 
999     RegreadNode *CloneTree(MapleAllocator &allocator) const override
1000     {
1001         return allocator.GetMemPool()->New<RegreadNode>(*this);
1002     }
1003 
GetRegIdx() const1004     PregIdx GetRegIdx() const
1005     {
1006         return regIdx;
1007     }
SetRegIdx(PregIdx reg)1008     void SetRegIdx(PregIdx reg)
1009     {
1010         regIdx = reg;
1011     }
1012 
1013 private:
1014     PregIdx regIdx = 0;  // 32bit, negative if special register
1015 };
1016 
1017 // for finally
1018 class StmtNode : public BaseNode, public PtrListNodeBase<StmtNode> {
1019 public:
1020     static std::atomic<uint32> stmtIDNext;  // for assigning stmtID, initialized to 1; 0 is reserved
1021     static uint32 lastPrintedLineNum;       // used during printing ascii output
1022     static uint16 lastPrintedColumnNum;
1023 
StmtNode(Opcode o)1024     explicit StmtNode(Opcode o) : BaseNode(o), PtrListNodeBase(), stmtID(stmtIDNext), stmtOriginalID(stmtIDNext)
1025     {
1026         ++stmtIDNext;
1027     }
1028 
StmtNode(Opcode o, uint8 numOpr)1029     StmtNode(Opcode o, uint8 numOpr)
1030         : BaseNode(o, numOpr), PtrListNodeBase(), stmtID(stmtIDNext), stmtOriginalID(stmtIDNext)
1031     {
1032         ++stmtIDNext;
1033     }
1034 
StmtNode(Opcode o, PrimType typ, uint8 numOpr)1035     StmtNode(Opcode o, PrimType typ, uint8 numOpr)
1036         : BaseNode(o, typ, numOpr), PtrListNodeBase(), stmtID(stmtIDNext), stmtOriginalID(stmtIDNext)
1037     {
1038         ++stmtIDNext;
1039     }
1040 
1041     // used for NaryStmtNode when clone
StmtNode(Opcode o, PrimType typ, uint8 numOpr, const SrcPosition &srcPosition, uint32 stmtOriginalID, StmtAttrs attrs)1042     StmtNode(Opcode o, PrimType typ, uint8 numOpr, const SrcPosition &srcPosition, uint32 stmtOriginalID,
1043              StmtAttrs attrs)
1044         : BaseNode(o, typ, numOpr),
1045           PtrListNodeBase(),
1046           srcPosition(srcPosition),
1047           stmtID(stmtIDNext),
1048           stmtOriginalID(stmtOriginalID),
1049           stmtAttrs(attrs)
1050     {
1051         ++stmtIDNext;
1052     }
1053 
1054     virtual ~StmtNode() = default;
1055 
1056 #ifdef ARK_LITECG_DEBUG
1057     using BaseNode::Dump;
1058     void DumpBase(int32 indent) const override;
1059     void Dump(int32 indent) const override;
1060 #endif
1061 
1062     virtual StmtNode *CloneTree(MapleAllocator &allocator) const override
1063     {
1064         auto *s = allocator.GetMemPool()->New<StmtNode>(*this);
1065         s->SetStmtID(stmtIDNext++);
1066         s->SetMeStmtID(meStmtID);
1067         return s;
1068     }
1069 
GetSrcPos() const1070     const SrcPosition &GetSrcPos() const
1071     {
1072         return srcPosition;
1073     }
1074 
GetSrcPos()1075     SrcPosition &GetSrcPos()
1076     {
1077         return srcPosition;
1078     }
1079 
SetSrcPos(SrcPosition pos)1080     void SetSrcPos(SrcPosition pos)
1081     {
1082         srcPosition = pos;
1083     }
1084 
GetStmtID() const1085     uint32 GetStmtID() const
1086     {
1087         return stmtID;
1088     }
1089 
SetStmtID(uint32 id)1090     void SetStmtID(uint32 id)
1091     {
1092         stmtID = id;
1093     }
1094 
GetOriginalID() const1095     uint32 GetOriginalID() const
1096     {
1097         return stmtOriginalID;
1098     }
1099 
SetOriginalID(uint32 id)1100     void SetOriginalID(uint32 id)
1101     {
1102         stmtOriginalID = id;
1103     }
1104 
GetMeStmtID() const1105     uint32 GetMeStmtID() const
1106     {
1107         return meStmtID;
1108     }
1109 
SetMeStmtID(uint32 id)1110     void SetMeStmtID(uint32 id)
1111     {
1112         meStmtID = id;
1113     }
1114 
GetRHS() const1115     virtual BaseNode *GetRHS() const
1116     {
1117         return nullptr;
1118     }
1119 
GetIsLive() const1120     bool GetIsLive() const
1121     {
1122         return isLive;
1123     }
1124 
SetIsLive(bool live) const1125     void SetIsLive(bool live) const
1126     {
1127         isLive = live;
1128     }
1129 
IsInSafeRegion() const1130     bool IsInSafeRegion() const
1131     {
1132         return stmtAttrs.GetAttr(STMTATTR_insaferegion);
1133     }
1134 
SetInSafeRegion()1135     void SetInSafeRegion()
1136     {
1137         stmtAttrs.SetAttr(STMTATTR_insaferegion);
1138     }
1139 
CopySafeRegionAttr(const StmtAttrs &stmtAttr)1140     void CopySafeRegionAttr(const StmtAttrs &stmtAttr)
1141     {
1142         this->stmtAttrs.AppendAttr(stmtAttr.GetTargetAttrFlag(STMTATTR_insaferegion));
1143     }
1144 
SetMayTailcall(bool flag = true)1145     void SetMayTailcall(bool flag = true)
1146     {
1147         stmtAttrs.SetAttr(STMTATTR_mayTailcall, flag);
1148     }
1149 
GetMayTailCall() const1150     bool GetMayTailCall() const
1151     {
1152         return stmtAttrs.GetAttr(STMTATTR_mayTailcall);
1153     }
1154 
GetStmtAttrs() const1155     const StmtAttrs &GetStmtAttrs() const
1156     {
1157         return stmtAttrs;
1158     }
1159 
SetAttr(StmtAttrKind x)1160     void SetAttr(StmtAttrKind x)
1161     {
1162         stmtAttrs.SetAttr(x);
1163     }
1164 
GetAttr(StmtAttrKind x) const1165     bool GetAttr(StmtAttrKind x) const
1166     {
1167         return stmtAttrs.GetAttr(x);
1168     }
1169 
SetStmtAttrs(StmtAttrs stmtAttrs_)1170     void SetStmtAttrs(StmtAttrs stmtAttrs_)
1171     {
1172         stmtAttrs = stmtAttrs_;
1173     }
1174 
1175 protected:
1176     SrcPosition srcPosition;
1177 
1178 private:
1179     uint32 stmtID;                // a unique ID assigned to it
1180     uint32 stmtOriginalID;        // first define id, no change when clone, need copy when emit from MeStmt
1181     uint32 meStmtID = 0;          // Need copy when emit from MeStmt, attention:this just for two stmt(if && call)
1182     mutable bool isLive = false;  // only used for dse to save compile time
1183                                   // mutable to keep const-ness at most situation
1184     StmtAttrs stmtAttrs;
1185 };
1186 
1187 class IassignNode : public StmtNode {
1188 public:
IassignNode()1189     IassignNode() : IassignNode(TyIdx(0), 0, nullptr, nullptr) {}
1190 
IassignNode(TyIdx tyIdx, FieldID fieldID, BaseNode *addrOpnd, BaseNode *rhsOpnd)1191     IassignNode(TyIdx tyIdx, FieldID fieldID, BaseNode *addrOpnd, BaseNode *rhsOpnd)
1192         : StmtNode(OP_iassign), tyIdx(tyIdx), fieldID(fieldID), addrExpr(addrOpnd), rhs(rhsOpnd)
1193     {
1194         BaseNodeT::SetNumOpnds(kOperandNumBinary);
1195     }
1196 
1197     virtual ~IassignNode() = default;
1198 
GetTyIdx() const1199     TyIdx GetTyIdx() const
1200     {
1201         return tyIdx;
1202     }
1203 
SetTyIdx(TyIdx idx)1204     void SetTyIdx(TyIdx idx)
1205     {
1206         tyIdx = idx;
1207     }
1208 
GetFieldID() const1209     FieldID GetFieldID() const
1210     {
1211         return fieldID;
1212     }
1213 
SetFieldID(FieldID fid)1214     void SetFieldID(FieldID fid)
1215     {
1216         fieldID = fid;
1217     }
1218 
1219     BaseNode *Opnd(size_t i) const override
1220     {
1221         if (i == 0) {
1222             return addrExpr;
1223         }
1224         return rhs;
1225     }
1226 
1227     size_t NumOpnds() const override
1228     {
1229         return kOperandNumBinary;
1230     }
1231 
1232     void SetOpnd(BaseNode *node, size_t i) override
1233     {
1234         if (i == 0) {
1235             addrExpr = node;
1236         } else {
1237             rhs = node;
1238         }
1239     }
1240 
1241 #ifdef ARK_LITECG_DEBUG
1242     void Dump(int32 indent) const override;
1243 #endif
1244 
1245     IassignNode *CloneTree(MapleAllocator &allocator) const override
1246     {
1247         auto *bn = allocator.GetMemPool()->New<IassignNode>(*this);
1248         bn->SetStmtID(stmtIDNext++);
1249         bn->SetOpnd(addrExpr->CloneTree(allocator), 0);
1250         bn->SetRHS(rhs->CloneTree(allocator));
1251         return bn;
1252     }
1253 
1254     // the base of an address expr is either a leaf or an iread
GetAddrExprBase() const1255     BaseNode &GetAddrExprBase() const
1256     {
1257         BaseNode *base = addrExpr;
1258         while (base->NumOpnds() != 0 && base->GetOpCode() != OP_iread) {
1259             base = base->Opnd(0);
1260         }
1261         return *base;
1262     }
1263 
SetAddrExpr(BaseNode *exp)1264     void SetAddrExpr(BaseNode *exp)
1265     {
1266         addrExpr = exp;
1267     }
1268 
1269     BaseNode *GetRHS() const override
1270     {
1271         return rhs;
1272     }
1273 
SetRHS(BaseNode *node)1274     void SetRHS(BaseNode *node)
1275     {
1276         rhs = node;
1277     }
1278 
1279 private:
1280     TyIdx tyIdx;
1281     FieldID fieldID;
1282 
1283 public:
1284     BaseNode *addrExpr;
1285     BaseNode *rhs;
1286 };
1287 
1288 // goto
1289 class GotoNode : public StmtNode {
1290 public:
GotoNode(Opcode o)1291     explicit GotoNode(Opcode o) : StmtNode(o) {}
1292 
GotoNode(Opcode o, uint32 ofst)1293     GotoNode(Opcode o, uint32 ofst) : StmtNode(o), offset(ofst) {}
1294 
1295     virtual ~GotoNode() = default;
1296 
1297 #ifdef ARK_LITECG_DEBUG
1298     void Dump(int32 indent) const override;
1299 #endif
1300 
1301     GotoNode *CloneTree(MapleAllocator &allocator) const override
1302     {
1303         auto *g = allocator.GetMemPool()->New<GotoNode>(*this);
1304         g->SetStmtID(stmtIDNext++);
1305         return g;
1306     }
1307 
GetOffset() const1308     uint32 GetOffset() const
1309     {
1310         return offset;
1311     }
1312 
SetOffset(uint32 o)1313     void SetOffset(uint32 o)
1314     {
1315         offset = o;
1316     }
1317 
1318 private:
1319     uint32 offset = 0;
1320 };
1321 
1322 using CasePair = std::pair<int64, LabelIdx>;
1323 using CaseVector = MapleVector<CasePair>;
1324 class SwitchNode : public StmtNode {
1325 public:
SwitchNode(MapleAllocator &allocator)1326     explicit SwitchNode(MapleAllocator &allocator) : StmtNode(OP_switch, 1), switchTable(allocator.Adapter()) {}
1327 
SwitchNode(const MIRModule &mod)1328     explicit SwitchNode(const MIRModule &mod) : SwitchNode(mod.GetCurFuncCodeMPAllocator()) {}
1329 
SwitchNode(MapleAllocator &allocator, LabelIdx label)1330     SwitchNode(MapleAllocator &allocator, LabelIdx label) : SwitchNode(allocator, label, nullptr) {}
1331 
SwitchNode(MapleAllocator &allocator, LabelIdx label, BaseNode *opnd)1332     SwitchNode(MapleAllocator &allocator, LabelIdx label, BaseNode *opnd)
1333         : StmtNode(OP_switch, 1), switchOpnd(opnd), defaultLabel(label), switchTable(allocator.Adapter())
1334     {
1335     }
1336 
SwitchNode(const MIRModule &mod, LabelIdx label)1337     SwitchNode(const MIRModule &mod, LabelIdx label) : SwitchNode(mod.GetCurFuncCodeMPAllocator(), label) {}
1338 
SwitchNode(MapleAllocator &allocator, const SwitchNode &node)1339     SwitchNode(MapleAllocator &allocator, const SwitchNode &node)
1340         : StmtNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds),
1341           defaultLabel(node.GetDefaultLabel()),
1342           switchTable(allocator.Adapter())
1343     {
1344     }
1345 
SwitchNode(const MIRModule &mod, const SwitchNode &node)1346     SwitchNode(const MIRModule &mod, const SwitchNode &node) : SwitchNode(mod.GetCurFuncCodeMPAllocator(), node) {}
1347 
1348     SwitchNode(SwitchNode &node) = delete;
1349     SwitchNode &operator=(const SwitchNode &node) = delete;
1350     virtual ~SwitchNode() = default;
1351 
1352 #ifdef ARK_LITECG_DEBUG
1353     void Dump(int32 indent) const override;
1354 #endif
1355 
1356     SwitchNode *CloneTree(MapleAllocator &allocator) const override
1357     {
1358         auto *node = allocator.GetMemPool()->New<SwitchNode>(allocator, *this);
1359         node->SetSwitchOpnd(switchOpnd->CloneTree(allocator));
1360         for (size_t i = 0; i < switchTable.size(); ++i) {
1361             node->InsertCasePair(switchTable[i]);
1362         }
1363         return node;
1364     }
1365 
1366     BaseNode *Opnd(size_t) const override
1367     {
1368         return switchOpnd;
1369     }
1370 
1371     void SetOpnd(BaseNode *node, size_t) override
1372     {
1373         switchOpnd = node;
1374     }
1375 
GetSwitchOpnd() const1376     BaseNode *GetSwitchOpnd() const
1377     {
1378         return switchOpnd;
1379     }
1380 
SetSwitchOpnd(BaseNode *node)1381     void SetSwitchOpnd(BaseNode *node)
1382     {
1383         switchOpnd = node;
1384     }
1385 
GetDefaultLabel() const1386     LabelIdx GetDefaultLabel() const
1387     {
1388         return defaultLabel;
1389     }
1390 
SetDefaultLabel(LabelIdx idx)1391     void SetDefaultLabel(LabelIdx idx)
1392     {
1393         defaultLabel = idx;
1394     }
1395 
GetSwitchTable() const1396     const CaseVector &GetSwitchTable() const
1397     {
1398         return switchTable;
1399     }
1400 
GetSwitchTable()1401     CaseVector &GetSwitchTable()
1402     {
1403         return switchTable;
1404     }
1405 
GetCasePair(size_t idx) const1406     CasePair GetCasePair(size_t idx) const
1407     {
1408         DEBUG_ASSERT(idx < switchTable.size(), "out of range in SwitchNode::GetCasePair");
1409         return switchTable.at(idx);
1410     }
1411 
1412     void SetSwitchTable(CaseVector vec)
1413     {
1414         switchTable = vec;
1415     }
1416 
1417     void InsertCasePair(CasePair pair)
1418     {
1419         switchTable.push_back(pair);
1420     }
1421 
1422     void UpdateCaseLabelAt(size_t i, LabelIdx idx)
1423     {
1424         switchTable[i] = std::make_pair(switchTable[i].first, idx);
1425     }
1426 
1427     void SortCasePair(bool func(const CasePair &, const CasePair &))
1428     {
1429         std::sort(switchTable.begin(), switchTable.end(), func);
1430     }
1431 
1432 private:
1433     BaseNode *switchOpnd = nullptr;
1434     LabelIdx defaultLabel = 0;
1435     CaseVector switchTable;
1436 };
1437 
1438 using MCasePair = std::pair<BaseNode *, LabelIdx>;
1439 using MCaseVector = MapleVector<MCasePair>;
1440 
1441 // eval, throw, free
1442 class UnaryStmtNode : public StmtNode {
1443 public:
1444     explicit UnaryStmtNode(Opcode o) : StmtNode(o, 1) {}
1445 
1446     UnaryStmtNode(Opcode o, PrimType typ) : StmtNode(o, typ, 1) {}
1447 
1448     UnaryStmtNode(Opcode o, PrimType typ, BaseNode *opnd) : StmtNode(o, typ, 1), uOpnd(opnd) {}
1449 
1450     virtual ~UnaryStmtNode() = default;
1451 
1452 #ifdef ARK_LITECG_DEBUG
1453     using StmtNode::Dump;
1454     void Dump(int32 indent) const override;
1455     void DumpOpnd(const MIRModule &mod, int32 indent) const;
1456     void DumpOpnd(int32 indent) const;
1457 #endif
1458 
1459     UnaryStmtNode *CloneTree(MapleAllocator &allocator) const override
1460     {
1461         auto *node = allocator.GetMemPool()->New<UnaryStmtNode>(*this);
1462         node->SetStmtID(stmtIDNext++);
1463         node->SetOpnd(uOpnd->CloneTree(allocator), 0);
1464         return node;
1465     }
1466 
1467     bool IsLeaf() const override
1468     {
1469         return false;
1470     }
1471 
1472     BaseNode *GetRHS() const override
1473     {
1474         return Opnd(0);
1475     }
1476 
1477     virtual void SetRHS(BaseNode *rhs)
1478     {
1479         this->SetOpnd(rhs, 0);
1480     }
1481 
1482     BaseNode *Opnd(size_t i = 0) const override
1483     {
1484         (void)i;
1485         return uOpnd;
1486     }
1487 
1488     void SetOpnd(BaseNode *node, size_t) override
1489     {
1490         uOpnd = node;
1491     }
1492 
1493 private:
1494     BaseNode *uOpnd = nullptr;
1495 };
1496 
1497 // dassign
1498 class DassignNode : public UnaryStmtNode {
1499 public:
1500     DassignNode() : UnaryStmtNode(OP_dassign), stIdx() {}
1501 
1502     explicit DassignNode(PrimType typ) : UnaryStmtNode(OP_dassign, typ), stIdx() {}
1503 
1504     DassignNode(PrimType typ, BaseNode *opnd) : UnaryStmtNode(OP_dassign, typ, opnd), stIdx() {}
1505 
1506     DassignNode(PrimType typ, BaseNode *opnd, StIdx idx, FieldID fieldID)
1507         : UnaryStmtNode(OP_dassign, typ, opnd), stIdx(idx), fieldID(fieldID)
1508     {
1509     }
1510 
1511     DassignNode(BaseNode *opnd, StIdx idx, FieldID fieldID) : DassignNode(kPtyInvalid, opnd, idx, fieldID) {}
1512 
1513     virtual ~DassignNode() = default;
1514 
1515 #ifdef ARK_LITECG_DEBUG
1516     void Dump(int32 indent) const override;
1517 #endif
1518 
1519     DassignNode *CloneTree(MapleAllocator &allocator) const override
1520     {
1521         auto *node = allocator.GetMemPool()->New<DassignNode>(*this);
1522         node->SetStmtID(stmtIDNext++);
1523         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
1524         return node;
1525     }
1526 
1527     size_t NumOpnds() const override
1528     {
1529         return 1;
1530     }
1531 
1532     bool IsIdentityDassign() const
1533     {
1534         BaseNode *rhs = GetRHS();
1535         if (rhs->GetOpCode() != OP_dread) {
1536             return false;
1537         }
1538         auto *dread = static_cast<AddrofNode *>(rhs);
1539         return (stIdx == dread->GetStIdx());
1540     }
1541 
1542     BaseNode *GetRHS() const override
1543     {
1544         return UnaryStmtNode::GetRHS();
1545     }
1546 
1547     void SetRHS(BaseNode *rhs) override
1548     {
1549         UnaryStmtNode::SetOpnd(rhs, 0);
1550     }
1551 
1552     StIdx GetStIdx() const
1553     {
1554         return stIdx;
1555     }
1556     void SetStIdx(StIdx s)
1557     {
1558         stIdx = s;
1559     }
1560 
1561     const FieldID &GetFieldID() const
1562     {
1563         return fieldID;
1564     }
1565 
1566     void SetFieldID(FieldID f)
1567     {
1568         fieldID = f;
1569     }
1570 
1571 private:
1572     StIdx stIdx;
1573     FieldID fieldID = 0;
1574 };
1575 
1576 class RegassignNode : public UnaryStmtNode {
1577 public:
1578     RegassignNode() : UnaryStmtNode(OP_regassign) {}
1579 
1580     RegassignNode(PrimType primType, PregIdx idx, BaseNode *opnd)
1581         : UnaryStmtNode(OP_regassign, primType, opnd), regIdx(idx)
1582     {
1583     }
1584 
1585     virtual ~RegassignNode() = default;
1586 
1587 #ifdef ARK_LITECG_DEBUG
1588     void Dump(int32 indent) const override;
1589 #endif
1590 
1591     RegassignNode *CloneTree(MapleAllocator &allocator) const override
1592     {
1593         auto *node = allocator.GetMemPool()->New<RegassignNode>(*this);
1594         node->SetStmtID(stmtIDNext++);
1595         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
1596         return node;
1597     }
1598 
1599     BaseNode *GetRHS() const override
1600     {
1601         return UnaryStmtNode::GetRHS();
1602     }
1603 
1604     void SetRHS(BaseNode *rhs) override
1605     {
1606         UnaryStmtNode::SetOpnd(rhs, 0);
1607     }
1608 
1609     PregIdx GetRegIdx() const
1610     {
1611         return regIdx;
1612     }
1613     void SetRegIdx(PregIdx idx)
1614     {
1615         regIdx = idx;
1616     }
1617 
1618 private:
1619     PregIdx regIdx = 0;  // 32bit, negative if special register
1620 };
1621 
1622 // brtrue and brfalse
1623 class CondGotoNode : public UnaryStmtNode {
1624 public:
1625     static const int32 probAll;
1626     explicit CondGotoNode(Opcode o) : CondGotoNode(o, 0, nullptr) {}
1627 
1628     CondGotoNode(Opcode o, uint32 offset, BaseNode *opnd) : UnaryStmtNode(o, kPtyInvalid, opnd), offset(offset)
1629     {
1630         BaseNodeT::SetNumOpnds(kOperandNumUnary);
1631     }
1632 
1633     virtual ~CondGotoNode() = default;
1634 
1635 #ifdef ARK_LITECG_DEBUG
1636     void Dump(int32 indent) const override;
1637 #endif
1638 
1639     uint32 GetOffset() const
1640     {
1641         return offset;
1642     }
1643 
1644     void SetOffset(uint32 offsetValue)
1645     {
1646         offset = offsetValue;
1647     }
1648 
1649     bool IsBranchProbValid() const
1650     {
1651         return branchProb > 0 && branchProb < probAll;
1652     }
1653 
1654     int32 GetBranchProb() const
1655     {
1656         return branchProb;
1657     }
1658 
1659     void SetBranchProb(int32 prob)
1660     {
1661         branchProb = prob;
1662     }
1663 
1664     void ReverseBranchProb()
1665     {
1666         if (IsBranchProbValid()) {
1667             branchProb = probAll - branchProb;
1668         }
1669     }
1670 
1671     void InvalidateBranchProb()
1672     {
1673         if (IsBranchProbValid()) {
1674             branchProb = -1;
1675         }
1676     }
1677 
1678     CondGotoNode *CloneTree(MapleAllocator &allocator) const override
1679     {
1680         auto *node = allocator.GetMemPool()->New<CondGotoNode>(*this);
1681         node->SetStmtID(stmtIDNext++);
1682         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
1683         return node;
1684     }
1685 
1686 private:
1687     uint32 offset;
1688     int32 branchProb = -1;  // branch probability, a negative number indicates that the probability is invalid
1689 };
1690 
1691 using SmallCasePair = std::pair<uint16, uint32>;
1692 using SmallCaseVector = MapleVector<SmallCasePair>;
1693 class RangeGotoNode : public UnaryStmtNode {
1694 public:
1695     explicit RangeGotoNode(MapleAllocator &allocator) : UnaryStmtNode(OP_rangegoto), rangegotoTable(allocator.Adapter())
1696     {
1697     }
1698 
1699     explicit RangeGotoNode(const MIRModule &mod) : RangeGotoNode(mod.GetCurFuncCodeMPAllocator()) {}
1700 
1701     RangeGotoNode(MapleAllocator &allocator, const RangeGotoNode &node)
1702         : UnaryStmtNode(node), tagOffset(node.tagOffset), rangegotoTable(allocator.Adapter())
1703     {
1704     }
1705 
1706     RangeGotoNode(const MIRModule &mod, const RangeGotoNode &node)
1707         : RangeGotoNode(mod.GetCurFuncCodeMPAllocator(), node)
1708     {
1709     }
1710 
1711     RangeGotoNode(RangeGotoNode &node) = delete;
1712     RangeGotoNode &operator=(const RangeGotoNode &node) = delete;
1713     virtual ~RangeGotoNode() = default;
1714 
1715 #ifdef ARK_LITECG_DEBUG
1716     void Dump(int32 indent) const override;
1717 #endif
1718 
1719     RangeGotoNode *CloneTree(MapleAllocator &allocator) const override
1720     {
1721         auto *node = allocator.GetMemPool()->New<RangeGotoNode>(allocator, *this);
1722         node->SetOpnd(Opnd(0)->CloneTree(allocator), 0);
1723         for (size_t i = 0; i < rangegotoTable.size(); ++i) {
1724             node->rangegotoTable.push_back(rangegotoTable[i]);
1725         }
1726         return node;
1727     }
1728 
1729     const SmallCaseVector &GetRangeGotoTable() const
1730     {
1731         return rangegotoTable;
1732     }
1733 
1734     const SmallCasePair &GetRangeGotoTableItem(size_t i) const
1735     {
1736         return rangegotoTable.at(i);
1737     }
1738 
1739     void SetRangeGotoTable(SmallCaseVector rt)
1740     {
1741         rangegotoTable = rt;
1742     }
1743 
1744     void AddRangeGoto(uint32 tag, LabelIdx idx)
1745     {
1746         rangegotoTable.push_back(SmallCasePair(tag, idx));
1747     }
1748 
1749     int32 GetTagOffset() const
1750     {
1751         return tagOffset;
1752     }
1753 
1754     void SetTagOffset(int32 offset)
1755     {
1756         tagOffset = offset;
1757     }
1758 
1759 private:
1760     int32 tagOffset = 0;
1761     // add each tag to tagOffset field to get the actual tag values
1762     SmallCaseVector rangegotoTable;
1763 };
1764 
1765 class BlockNode : public StmtNode {
1766 public:
1767     using StmtNodes = PtrListRef<StmtNode>;
1768 
1769     BlockNode() : StmtNode(OP_block) {}
1770 
1771     ~BlockNode()
1772     {
1773         stmtNodeList.clear();
1774     }
1775 
1776     void AddStatement(StmtNode *stmt);
1777     void AppendStatementsFromBlock(BlockNode &blk);
1778     void InsertFirst(StmtNode *stmt);  // Insert stmt as the first
1779     void InsertLast(StmtNode *stmt);   // Insert stmt as the last
1780     void RemoveStmt(const StmtNode *stmtNode1);
1781     void InsertBefore(const StmtNode *stmtNode1, StmtNode *stmtNode2);  // Insert ss2 before ss1 in current block.
1782     void InsertAfter(const StmtNode *stmtNode1, StmtNode *stmtNode2);   // Insert ss2 after ss1 in current block
1783 
1784 #ifdef ARK_LITECG_DEBUG
1785     void Dump(int32 indent, const MIRSymbolTable *theSymTab, MIRPregTable *thePregTab, bool withInfo, bool isFuncbody,
1786               MIRFlavor flavor) const;
1787 
1788     void Dump(int32 indent) const override
1789     {
1790         Dump(indent, nullptr, nullptr, false, false, kFlavorUnknown);
1791     }
1792 #endif
1793 
1794     BlockNode *CloneTree(MapleAllocator &allocator) const override
1795     {
1796         auto *blk = allocator.GetMemPool()->New<BlockNode>();
1797         blk->SetStmtID(stmtIDNext++);
1798         for (auto &stmt : stmtNodeList) {
1799             StmtNode *newStmt = static_cast<StmtNode *>(stmt.CloneTree(allocator));
1800             DEBUG_ASSERT(newStmt != nullptr, "null ptr check");
1801             newStmt->SetPrev(nullptr);
1802             newStmt->SetNext(nullptr);
1803             blk->AddStatement(newStmt);
1804         }
1805         return blk;
1806     }
1807 
1808     BlockNode *CloneTreeWithSrcPosition(const MIRModule &mod)
1809     {
1810         MapleAllocator &allocator = mod.GetCurFuncCodeMPAllocator();
1811         auto *blk = allocator.GetMemPool()->New<BlockNode>();
1812         blk->SetStmtID(stmtIDNext++);
1813         for (auto &stmt : stmtNodeList) {
1814             StmtNode *newStmt = static_cast<StmtNode *>(stmt.CloneTree(allocator));
1815             DEBUG_ASSERT(newStmt != nullptr, "null ptr check");
1816             newStmt->SetSrcPos(stmt.GetSrcPos());
1817             newStmt->SetPrev(nullptr);
1818             newStmt->SetNext(nullptr);
1819             blk->AddStatement(newStmt);
1820         }
1821         return blk;
1822     }
1823 
1824     bool IsEmpty() const
1825     {
1826         return stmtNodeList.empty();
1827     }
1828 
1829     void ResetBlock()
1830     {
1831         stmtNodeList.clear();
1832     }
1833 
1834     StmtNode *GetFirst()
1835     {
1836         return &(stmtNodeList.front());
1837     }
1838 
1839     const StmtNode *GetFirst() const
1840     {
1841         return &(stmtNodeList.front());
1842     }
1843 
1844     void SetFirst(StmtNode *node)
1845     {
1846         stmtNodeList.update_front(node);
1847     }
1848 
1849     StmtNode *GetLast()
1850     {
1851         return &(stmtNodeList.back());
1852     }
1853 
1854     const StmtNode *GetLast() const
1855     {
1856         return &(stmtNodeList.back());
1857     }
1858 
1859     void SetLast(StmtNode *node)
1860     {
1861         stmtNodeList.update_back(node);
1862     }
1863 
1864     StmtNodes &GetStmtNodes()
1865     {
1866         return stmtNodeList;
1867     }
1868 
1869     const StmtNodes &GetStmtNodes() const
1870     {
1871         return stmtNodeList;
1872     }
1873 
1874 private:
1875     StmtNodes stmtNodeList;
1876 };
1877 
1878 class IfStmtNode : public UnaryStmtNode {
1879 public:
1880     IfStmtNode() : UnaryStmtNode(OP_if)
1881     {
1882         numOpnds = kOperandNumTernary;
1883     }
1884 
1885     virtual ~IfStmtNode() = default;
1886 
1887 #ifdef ARK_LITECG_DEBUG
1888     void Dump(int32 indent) const override;
1889 #endif
1890 
1891     IfStmtNode *CloneTree(MapleAllocator &allocator) const override
1892     {
1893         auto *node = allocator.GetMemPool()->New<IfStmtNode>(*this);
1894         node->SetStmtID(stmtIDNext++);
1895         CHECK_NULL_FATAL(Opnd());
1896         node->SetOpnd(Opnd()->CloneTree(allocator), 0);
1897         node->thenPart = thenPart->CloneTree(allocator);
1898         if (elsePart != nullptr) {
1899             node->elsePart = elsePart->CloneTree(allocator);
1900         }
1901         node->SetMeStmtID(GetMeStmtID());
1902         return node;
1903     }
1904 
1905     BaseNode *Opnd(size_t i = kFirstOpnd) const override
1906     {
1907         if (i == kFirstOpnd) {
1908             return UnaryStmtNode::Opnd(kFirstOpnd);
1909         } else if (i == kSecondOpnd) {
1910             return thenPart;
1911         } else if (i == kThirdOpnd) {
1912             DEBUG_ASSERT(elsePart != nullptr, "IfStmtNode has wrong numOpnds field, the elsePart is nullptr");
1913             DEBUG_ASSERT(numOpnds == kOperandNumTernary,
1914                          "IfStmtNode has wrong numOpnds field, the elsePart is nullptr");
1915             return elsePart;
1916         }
1917         DEBUG_ASSERT(false, "IfStmtNode has wrong numOpnds field: %u", NumOpnds());
1918         return nullptr;
1919     }
1920 
1921     BlockNode *GetThenPart() const
1922     {
1923         return thenPart;
1924     }
1925 
1926     void SetThenPart(BlockNode *node)
1927     {
1928         thenPart = node;
1929     }
1930 
1931     BlockNode *GetElsePart() const
1932     {
1933         return elsePart;
1934     }
1935 
1936     void SetElsePart(BlockNode *node)
1937     {
1938         elsePart = node;
1939     }
1940 
1941     size_t NumOpnds() const override
1942     {
1943         if (elsePart == nullptr) {
1944             return kOperandNumBinary;
1945         }
1946         return kOperandNumTernary;
1947     }
1948 
1949 private:
1950     BlockNode *thenPart = nullptr;
1951     BlockNode *elsePart = nullptr;
1952 };
1953 
1954 class BinaryStmtNode : public StmtNode, public BinaryOpnds {
1955 public:
1956     explicit BinaryStmtNode(Opcode o) : StmtNode(o, kOperandNumBinary) {}
1957 
1958     virtual ~BinaryStmtNode() = default;
1959 
1960 #ifdef ARK_LITECG_DEBUG
1961     void Dump(int32 indent) const override;
1962 #endif
1963 
1964     BinaryStmtNode *CloneTree(MapleAllocator &allocator) const override
1965     {
1966         auto *node = allocator.GetMemPool()->New<BinaryStmtNode>(*this);
1967         node->SetStmtID(stmtIDNext++);
1968         node->SetBOpnd(GetBOpnd(0)->CloneTree(allocator), 0);
1969         node->SetBOpnd(GetBOpnd(1)->CloneTree(allocator), 1);
1970         return node;
1971     }
1972 
1973     BaseNode *Opnd(size_t i) const override
1974     {
1975         DEBUG_ASSERT(i < kOperandNumBinary, "Invalid operand idx in BinaryStmtNode");
1976         DEBUG_ASSERT(i >= 0, "Invalid operand idx in BinaryStmtNode");
1977         return GetBOpnd(i);
1978     }
1979 
1980     size_t NumOpnds() const override
1981     {
1982         return kOperandNumBinary;
1983     }
1984 
1985     void SetOpnd(BaseNode *node, size_t i) override
1986     {
1987         SetBOpnd(node, i);
1988     }
1989 
1990     bool IsLeaf() const override
1991     {
1992         return false;
1993     }
1994 };
1995 
1996 // used by return
1997 class NaryStmtNode : public StmtNode, public NaryOpnds {
1998 public:
1999     NaryStmtNode(MapleAllocator &allocator, Opcode o) : StmtNode(o), NaryOpnds(allocator) {}
2000 
2001     NaryStmtNode(const MIRModule &mod, Opcode o) : NaryStmtNode(mod.GetCurFuncCodeMPAllocator(), o) {}
2002 
2003     NaryStmtNode(MapleAllocator &allocator, const NaryStmtNode &node)
2004         // do not use stmt copy constructor
2005         : StmtNode(node.GetOpCode(), node.GetPrimType(), node.numOpnds, node.GetSrcPos(), node.GetOriginalID(),
2006                    node.GetStmtAttrs()),
2007           NaryOpnds(allocator)
2008     {
2009     }
2010 
2011     NaryStmtNode(const MIRModule &mod, const NaryStmtNode &node) : NaryStmtNode(mod.GetCurFuncCodeMPAllocator(), node)
2012     {
2013     }
2014 
2015     explicit NaryStmtNode(const NaryStmtNode &node) = delete;
2016     NaryStmtNode &operator=(const NaryStmtNode &node) = delete;
2017     virtual ~NaryStmtNode() = default;
2018 
2019 #ifdef ARK_LITECG_DEBUG
2020     void Dump(int32 indent) const override;
2021     void DumpCallConvInfo() const
2022     {
2023         if (GetAttr(STMTATTR_ccall)) {
2024             LogInfo::MapleLogger() << " ccall";
2025         } else if (GetAttr(STMTATTR_webkitjscall)) {
2026             LogInfo::MapleLogger() << " webkitjscc";
2027         } else {
2028             // default is ccall
2029             LogInfo::MapleLogger() << " ccall";
2030         }
2031     }
2032 #endif
2033 
2034     NaryStmtNode *CloneTree(MapleAllocator &allocator) const override
2035     {
2036         auto *node = allocator.GetMemPool()->New<NaryStmtNode>(allocator, *this);
2037         for (size_t i = 0; i < GetNopndSize(); ++i) {
2038             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
2039         }
2040         node->SetNumOpnds(GetNopndSize());
2041         return node;
2042     }
2043 
2044     BaseNode *Opnd(size_t i) const override
2045     {
2046         return GetNopndAt(i);
2047     }
2048 
2049     void SetOpnd(BaseNode *node, size_t i) override
2050     {
2051         DEBUG_ASSERT(i < GetNopnd().size(), "array index out of range");
2052         SetNOpndAt(i, node);
2053     }
2054 
2055     size_t NumOpnds() const override
2056     {
2057         DEBUG_ASSERT(numOpnds == GetNopndSize(), "NaryStmtNode has wrong numOpnds field");
2058         return GetNopndSize();
2059     }
2060 
2061     void SetOpnds(const MapleVector<BaseNode *> &arguments)
2062     {
2063         SetNOpnd(arguments);
2064         SetNumOpnds(arguments.size());
2065     }
2066 
2067     void PushOpnd(BaseNode *node)
2068     {
2069         if (node != nullptr) {
2070             GetNopnd().push_back(node);
2071         }
2072         SetNumOpnds(GetNopndSize());
2073     }
2074 
2075     void InsertOpnd(BaseNode *node, size_t idx)
2076     {
2077         if (node == nullptr || idx > GetNopndSize()) {
2078             return;
2079         }
2080         auto begin = GetNopnd().begin();
2081         for (size_t i = 0; i < idx; ++i) {
2082             ++begin;
2083         }
2084         (void)GetNopnd().insert(begin, node);
2085         SetNumOpnds(GetNopndSize());
2086     }
2087 };
2088 
2089 class SafetyCheckStmtNode {
2090 public:
2091     explicit SafetyCheckStmtNode(GStrIdx funcNameIdx) : funcNameIdx(funcNameIdx) {}
2092     explicit SafetyCheckStmtNode(const SafetyCheckStmtNode &stmtNode) : funcNameIdx(stmtNode.GetFuncNameIdx()) {}
2093 
2094     virtual ~SafetyCheckStmtNode() = default;
2095 
2096 #ifdef ARK_LITECG_DEBUG
2097     std::string GetFuncName() const;
2098 #endif
2099 
2100     GStrIdx GetFuncNameIdx() const
2101     {
2102         return funcNameIdx;
2103     }
2104 
2105 #ifdef ARK_LITECG_DEBUG
2106     void Dump() const
2107     {
2108         LogInfo::MapleLogger() << " <&" << GetFuncName() << ">";
2109     }
2110 #endif
2111 
2112 private:
2113     GStrIdx funcNameIdx;
2114 };
2115 
2116 // used by call,
2117 // callassigned,
2118 class CallNode : public NaryStmtNode, public DeoptBundleInfo {
2119 public:
2120     CallNode(MapleAllocator &allocator, Opcode o)
2121         : NaryStmtNode(allocator, o), DeoptBundleInfo(allocator), returnValues(allocator.Adapter())
2122     {
2123     }
2124 
2125     CallNode(MapleAllocator &allocator, Opcode o, PUIdx idx) : CallNode(allocator, o, idx, TyIdx()) {}
2126 
2127     CallNode(MapleAllocator &allocator, Opcode o, PUIdx idx, TyIdx tdx)
2128         : NaryStmtNode(allocator, o),
2129           DeoptBundleInfo(allocator),
2130           puIdx(idx),
2131           tyIdx(tdx),
2132           returnValues(allocator.Adapter())
2133     {
2134     }
2135 
2136     CallNode(const MIRModule &mod, Opcode o) : CallNode(mod.GetCurFuncCodeMPAllocator(), o) {}
2137 
2138     CallNode(const MIRModule &mod, Opcode o, PUIdx idx, TyIdx tdx)
2139         : CallNode(mod.GetCurFuncCodeMPAllocator(), o, idx, tdx)
2140     {
2141     }
2142 
2143     CallNode(MapleAllocator &allocator, const CallNode &node)
2144         : NaryStmtNode(allocator, node),
2145           DeoptBundleInfo(allocator),
2146           puIdx(node.GetPUIdx()),
2147           tyIdx(node.tyIdx),
2148           returnValues(allocator.Adapter())
2149     {
2150     }
2151 
2152     CallNode(const MIRModule &mod, const CallNode &node) : CallNode(mod.GetCurFuncCodeMPAllocator(), node) {}
2153 
2154     CallNode(CallNode &node) = delete;
2155     CallNode &operator=(const CallNode &node) = delete;
2156     virtual ~CallNode() = default;
2157 
2158 #ifdef ARK_LITECG_DEBUG
2159     virtual void Dump(int32 indent, bool newline) const;
2160 #endif
2161 
2162     CallNode *CloneTree(MapleAllocator &allocator) const override
2163     {
2164         auto *node = allocator.GetMemPool()->New<CallNode>(allocator, *this);
2165         for (size_t i = 0; i < GetNopndSize(); ++i) {
2166             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
2167         }
2168         for (size_t i = 0; i < returnValues.size(); ++i) {
2169             node->GetReturnVec().push_back(returnValues[i]);
2170         }
2171         node->SetNumOpnds(GetNopndSize());
2172         for (const auto &elem : GetDeoptBundleInfo()) {
2173             node->AddDeoptBundleInfo(elem.first, elem.second);
2174         }
2175         return node;
2176     }
2177 
2178     PUIdx GetPUIdx() const
2179     {
2180         return puIdx;
2181     }
2182 
2183     void SetPUIdx(const PUIdx idx)
2184     {
2185         puIdx = idx;
2186     }
2187 
2188     TyIdx GetTyIdx() const
2189     {
2190         return tyIdx;
2191     }
2192 
2193     void SetTyIdx(TyIdx idx)
2194     {
2195         tyIdx = idx;
2196     }
2197 
2198     CallReturnVector &GetReturnVec()
2199     {
2200         return returnValues;
2201     }
2202 
2203     CallReturnPair GetReturnPair(size_t idx) const
2204     {
2205         DEBUG_ASSERT(idx < returnValues.size(), "out of range in CallNode::GetReturnPair");
2206         return returnValues.at(idx);
2207     }
2208 
2209     void SetReturnPair(CallReturnPair retVal, size_t idx)
2210     {
2211         DEBUG_ASSERT(idx < returnValues.size(), "out of range in CallNode::GetReturnPair");
2212         returnValues.at(idx) = retVal;
2213     }
2214 
2215     const CallReturnVector &GetReturnVec() const
2216     {
2217         return returnValues;
2218     }
2219 
2220     CallReturnPair GetNthReturnVec(size_t i) const
2221     {
2222         DEBUG_ASSERT(i < returnValues.size(), "array index out of range");
2223         return returnValues[i];
2224     }
2225 
2226     void SetReturnVec(const CallReturnVector &vec)
2227     {
2228         returnValues = vec;
2229     }
2230 
2231     size_t NumOpnds() const override
2232     {
2233         DEBUG_ASSERT(numOpnds == GetNopndSize(), "CallNode has wrong numOpnds field");
2234         return GetNopndSize();
2235     }
2236 
2237 #ifdef ARK_LITECG_DEBUG
2238     void Dump(int32 indent) const override
2239     {
2240         Dump(indent, true);
2241     }
2242 #endif
2243 
2244     CallReturnVector *GetCallReturnVector() override
2245     {
2246         return &returnValues;
2247     }
2248 
2249     void SetCallReturnVector(const CallReturnVector &value)
2250     {
2251         returnValues = value;
2252     }
2253 
2254 private:
2255     PUIdx puIdx = 0;
2256     TyIdx tyIdx = TyIdx(0);
2257     CallReturnVector returnValues;
2258 };
2259 
2260 // icall, icallassigned, icallproto and icallprotoassigned
2261 class IcallNode : public NaryStmtNode, public DeoptBundleInfo {
2262 public:
2263     IcallNode(MapleAllocator &allocator, Opcode o)
2264         : NaryStmtNode(allocator, o), DeoptBundleInfo(allocator), retTyIdx(0), returnValues(allocator.Adapter())
2265     {
2266         BaseNodeT::SetNumOpnds(kOperandNumUnary);
2267     }
2268 
2269     IcallNode(MapleAllocator &allocator, Opcode o, TyIdx idx)
2270         : NaryStmtNode(allocator, o), DeoptBundleInfo(allocator), retTyIdx(idx), returnValues(allocator.Adapter())
2271     {
2272         BaseNodeT::SetNumOpnds(kOperandNumUnary);
2273     }
2274 
2275     IcallNode(const MIRModule &mod, Opcode o) : IcallNode(mod.GetCurFuncCodeMPAllocator(), o) {}
2276 
2277     IcallNode(const MIRModule &mod, Opcode o, TyIdx idx) : IcallNode(mod.GetCurFuncCodeMPAllocator(), o, idx) {}
2278 
2279     IcallNode(MapleAllocator &allocator, const IcallNode &node)
2280         : NaryStmtNode(allocator, node),
2281           DeoptBundleInfo(allocator),
2282           retTyIdx(node.retTyIdx),
2283           returnValues(allocator.Adapter())
2284     {
2285     }
2286 
2287     IcallNode(const MIRModule &mod, const IcallNode &node) : IcallNode(mod.GetCurFuncCodeMPAllocator(), node) {}
2288 
2289     IcallNode(IcallNode &node) = delete;
2290     IcallNode &operator=(const IcallNode &node) = delete;
2291     virtual ~IcallNode() = default;
2292 
2293 #ifdef ARK_LITECG_DEBUG
2294     virtual void Dump(int32 indent, bool newline) const;
2295 #endif
2296 
2297     MIRType *GetCallReturnType() override;
2298     IcallNode *CloneTree(MapleAllocator &allocator) const override
2299     {
2300         auto *node = allocator.GetMemPool()->New<IcallNode>(allocator, *this);
2301         for (size_t i = 0; i < GetNopndSize(); ++i) {
2302             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
2303         }
2304         for (size_t i = 0; i < returnValues.size(); ++i) {
2305             node->returnValues.push_back(returnValues[i]);
2306         }
2307         node->SetNumOpnds(GetNopndSize());
2308         for (const auto &elem : GetDeoptBundleInfo()) {
2309             node->AddDeoptBundleInfo(elem.first, elem.second);
2310         }
2311         return node;
2312     }
2313 
2314     TyIdx GetRetTyIdx() const
2315     {
2316         return retTyIdx;
2317     }
2318 
2319     void SetRetTyIdx(TyIdx idx)
2320     {
2321         retTyIdx = idx;
2322     }
2323 
2324     const CallReturnVector &GetReturnVec() const
2325     {
2326         return returnValues;
2327     }
2328 
2329     CallReturnVector &GetReturnVec()
2330     {
2331         return returnValues;
2332     }
2333 
2334     void SetReturnVec(const CallReturnVector &vec)
2335     {
2336         returnValues = vec;
2337     }
2338 
2339     size_t NumOpnds() const override
2340     {
2341         DEBUG_ASSERT(numOpnds == GetNopndSize(), "IcallNode has wrong numOpnds field");
2342         return GetNopndSize();
2343     }
2344 
2345 #ifdef ARK_LITECG_DEBUG
2346     void Dump(int32 indent) const override
2347     {
2348         Dump(indent, true);
2349     }
2350 #endif
2351 
2352     CallReturnVector *GetCallReturnVector() override
2353     {
2354         return &returnValues;
2355     }
2356 
2357 private:
2358     TyIdx retTyIdx;  // for icall: return type for callee; for icallproto: the prototye
2359     // the 0th operand is the function pointer
2360     CallReturnVector returnValues;
2361 };
2362 
2363 // used by intrinsiccall
2364 class IntrinsiccallNode : public NaryStmtNode, public DeoptBundleInfo {
2365 public:
2366     IntrinsiccallNode(MapleAllocator &allocator, Opcode o)
2367         : NaryStmtNode(allocator, o),
2368           DeoptBundleInfo(allocator),
2369           intrinsic(INTRN_UNDEFINED),
2370           tyIdx(0),
2371           returnValues(allocator.Adapter())
2372     {
2373     }
2374 
2375     IntrinsiccallNode(MapleAllocator &allocator, Opcode o, MIRIntrinsicID id)
2376         : NaryStmtNode(allocator, o),
2377           DeoptBundleInfo(allocator),
2378           intrinsic(id),
2379           tyIdx(0),
2380           returnValues(allocator.Adapter())
2381     {
2382     }
2383 
2384     IntrinsiccallNode(const MIRModule &mod, Opcode o) : IntrinsiccallNode(mod.GetCurFuncCodeMPAllocator(), o) {}
2385 
2386     IntrinsiccallNode(const MIRModule &mod, Opcode o, MIRIntrinsicID id)
2387         : IntrinsiccallNode(mod.GetCurFuncCodeMPAllocator(), o, id)
2388     {
2389     }
2390 
2391     IntrinsiccallNode(MapleAllocator &allocator, const IntrinsiccallNode &node)
2392         : NaryStmtNode(allocator, node),
2393           DeoptBundleInfo(allocator),
2394           intrinsic(node.GetIntrinsic()),
2395           tyIdx(node.tyIdx),
2396           returnValues(allocator.Adapter())
2397     {
2398     }
2399 
2400     IntrinsiccallNode(const MIRModule &mod, const IntrinsiccallNode &node)
2401         : IntrinsiccallNode(mod.GetCurFuncCodeMPAllocator(), node)
2402     {
2403     }
2404 
2405     IntrinsiccallNode(IntrinsiccallNode &node) = delete;
2406     IntrinsiccallNode &operator=(const IntrinsiccallNode &node) = delete;
2407     virtual ~IntrinsiccallNode() = default;
2408 
2409 #ifdef ARK_LITECG_DEBUG
2410     virtual void Dump(int32 indent, bool newline) const;
2411 #endif
2412 
2413     IntrinsiccallNode *CloneTree(MapleAllocator &allocator) const override
2414     {
2415         auto *node = allocator.GetMemPool()->New<IntrinsiccallNode>(allocator, *this);
2416         for (size_t i = 0; i < GetNopndSize(); ++i) {
2417             node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
2418         }
2419         for (size_t i = 0; i < returnValues.size(); ++i) {
2420             node->GetReturnVec().push_back(returnValues[i]);
2421         }
2422         node->SetNumOpnds(GetNopndSize());
2423         return node;
2424     }
2425 
2426     MIRIntrinsicID GetIntrinsic() const
2427     {
2428         return intrinsic;
2429     }
2430 
2431     void SetIntrinsic(MIRIntrinsicID id)
2432     {
2433         intrinsic = id;
2434     }
2435 
2436     TyIdx GetTyIdx() const
2437     {
2438         return tyIdx;
2439     }
2440 
2441     void SetTyIdx(TyIdx idx)
2442     {
2443         tyIdx = idx;
2444     }
2445 
2446     CallReturnVector &GetReturnVec()
2447     {
2448         return returnValues;
2449     }
2450 
2451     const CallReturnVector &GetReturnVec() const
2452     {
2453         return returnValues;
2454     }
2455 
2456     void SetReturnVec(const CallReturnVector &vec)
2457     {
2458         returnValues = vec;
2459     }
2460 
2461     size_t NumOpnds() const override
2462     {
2463         DEBUG_ASSERT(numOpnds == GetNopndSize(), "IntrinsiccallNode has wrong numOpnds field");
2464         return GetNopndSize();
2465     }
2466 
2467 #ifdef ARK_LITECG_DEBUG
2468     void Dump(int32 indent) const override
2469     {
2470         Dump(indent, true);
2471     }
2472 #endif
2473 
2474     CallReturnVector *GetCallReturnVector() override
2475     {
2476         return &returnValues;
2477     }
2478 
2479     CallReturnPair &GetCallReturnPair(uint32 i)
2480     {
2481         DEBUG_ASSERT(i < returnValues.size(), "array index out of range");
2482         return returnValues.at(i);
2483     }
2484 
2485 private:
2486     MIRIntrinsicID intrinsic;
2487     TyIdx tyIdx;
2488     CallReturnVector returnValues;
2489 };
2490 
2491 class LabelNode : public StmtNode {
2492 public:
2493     LabelNode() : StmtNode(OP_label) {}
2494 
2495     explicit LabelNode(LabelIdx idx) : StmtNode(OP_label), labelIdx(idx) {}
2496 
2497     virtual ~LabelNode() = default;
2498 
2499 #ifdef ARK_LITECG_DEBUG
2500     void Dump(int32 indent) const override;
2501 #endif
2502 
2503     LabelNode *CloneTree(MapleAllocator &allocator) const override
2504     {
2505         auto *l = allocator.GetMemPool()->New<LabelNode>(*this);
2506         l->SetStmtID(stmtIDNext++);
2507         return l;
2508     }
2509 
2510     LabelIdx GetLabelIdx() const
2511     {
2512         return labelIdx;
2513     }
2514 
2515     void SetLabelIdx(LabelIdx idx)
2516     {
2517         labelIdx = idx;
2518     }
2519 
2520 private:
2521     LabelIdx labelIdx = 0;
2522 };
2523 
2524 class CommentNode : public StmtNode {
2525 public:
2526     explicit CommentNode(const MapleAllocator &allocator) : StmtNode(OP_comment), comment(allocator.GetMemPool()) {}
2527 
2528     explicit CommentNode(const MIRModule &mod) : CommentNode(mod.GetCurFuncCodeMPAllocator()) {}
2529 
2530     CommentNode(const MapleAllocator &allocator, const std::string &cmt)
2531         : StmtNode(OP_comment), comment(cmt, allocator.GetMemPool())
2532     {
2533     }
2534 
2535     CommentNode(const MIRModule &mod, const std::string &cmt) : CommentNode(mod.GetCurFuncCodeMPAllocator(), cmt) {}
2536 
2537     CommentNode(const MapleAllocator &allocator, const CommentNode &node)
2538         : StmtNode(node.GetOpCode(), node.GetPrimType()), comment(node.comment, allocator.GetMemPool())
2539     {
2540     }
2541 
2542     CommentNode(const MIRModule &mod, const CommentNode &node) : CommentNode(mod.GetCurFuncCodeMPAllocator(), node) {}
2543 
2544     CommentNode(CommentNode &node) = delete;
2545     CommentNode &operator=(const CommentNode &node) = delete;
2546     virtual ~CommentNode() = default;
2547 
2548 #ifdef ARK_LITECG_DEBUG
2549     void Dump(int32 indent) const override;
2550 #endif
2551 
2552     CommentNode *CloneTree(MapleAllocator &allocator) const override
2553     {
2554         auto *c = allocator.GetMemPool()->New<CommentNode>(allocator, *this);
2555         return c;
2556     }
2557 
2558     const MapleString &GetComment() const
2559     {
2560         return comment;
2561     }
2562 
2563     void SetComment(MapleString com)
2564     {
2565         comment = com;
2566     }
2567 
2568     void SetComment(const std::string &str)
2569     {
2570         comment = str;
2571     }
2572 
2573     void SetComment(const char *str)
2574     {
2575         comment = str;
2576     }
2577 
2578     void Append(const std::string &str)
2579     {
2580         comment += str;
2581     }
2582 
2583 private:
2584     MapleString comment;
2585 };
2586 
2587 enum AsmQualifierKind : unsigned {  // they are alreadgy Maple IR keywords
2588     kASMvolatile,
2589     kASMinline,
2590     kASMgoto,
2591 };
2592 
2593 #ifdef ARK_LITECG_DEBUG
2594 void DumpCallReturns(const MIRModule &mod, CallReturnVector nrets, int32 indent);
2595 #endif
2596 }  // namespace maple
2597 
2598 #define LOAD_SAFE_CAST_FOR_MIR_NODE
2599 #include "ir_safe_cast_traits.def"
2600 
2601 #endif  // MAPLE_IR_INCLUDE_MIR_NODES_H
2602