• 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_ME_INCLUDE_ME_IR_H
17 #define MAPLE_ME_INCLUDE_ME_IR_H
18 #include <array>
19 #include "orig_symbol.h"
20 #include "bb.h"
21 
22 namespace maple {
23 class PhiNode;    // circular dependency exists, no other choice
24 class MeStmt;     // circular dependency exists, no other choice
25 class IRMap;      // circular dependency exists, no other choice
26 class SSATab;     // circular dependency exists, no other choice
27 class VarMeExpr;  // circular dependency exists, no other choice
28 class Dominance;  // circular dependency exists, no other choice
29 using MeStmtPtr = MeStmt *;
30 enum MeExprOp : uint8 {
31     kMeOpUnknown,
32     kMeOpVar,
33     kMeOpIvar,
34     kMeOpAddrof,
35     kMeOpAddroffunc,
36     kMeOpAddroflabel,
37     kMeOpGcmalloc,
38     kMeOpReg,
39     kMeOpConst,
40     kMeOpConststr,
41     kMeOpConststr16,
42     kMeOpSizeoftype,
43     kMeOpFieldsDist,
44     kMeOpOp,
45 };  // cache the op to avoid dynamic cast
46 
47 constexpr int kInvalidExprID = -1;
48 class MeExpr {
49 public:
MeExpr(int32 exprId,MeExprOp meop,Opcode op,PrimType t,size_t n)50     MeExpr(int32 exprId, MeExprOp meop, Opcode op, PrimType t, size_t n)
51         : op(op), primType(t), numOpnds(n), meOp(meop), exprID(exprId)
52     {
53     }
54 
55     virtual ~MeExpr() = default;
56 
SetOp(Opcode opcode)57     void SetOp(Opcode opcode)
58     {
59         op = opcode;
60     }
61 
SetPtyp(PrimType primTypeVal)62     void SetPtyp(PrimType primTypeVal)
63     {
64         primType = primTypeVal;
65     }
66 
SetNumOpnds(uint8 val)67     void SetNumOpnds(uint8 val)
68     {
69         numOpnds = val;
70     }
71 
SetTreeID(uint32 val)72     void SetTreeID(uint32 val)
73     {
74         treeID = val;
75     }
76 
SetNext(MeExpr * nextPara)77     void SetNext(MeExpr *nextPara)
78     {
79         next = nextPara;
80     }
81 
GetOp()82     Opcode GetOp() const
83     {
84         return op;
85     }
86 
GetPrimType()87     PrimType GetPrimType() const
88     {
89         return primType;
90     }
91 
GetNumOpnds()92     uint8 GetNumOpnds() const
93     {
94         return numOpnds;
95     }
96 
GetMeOp()97     MeExprOp GetMeOp() const
98     {
99         return meOp;
100     }
101 
GetExprID()102     int32 GetExprID() const
103     {
104         return exprID;
105     }
106 
GetTreeID()107     uint32 GetTreeID() const
108     {
109         return treeID;
110     }
111 
GetNext()112     MeExpr *GetNext() const
113     {
114         return next;
115     }
116 
117     virtual void Dump(const IRMap *, int32 indent = 0) const
118     {
119         (void)indent;
120     }
121 
GetDepth()122     virtual uint8 GetDepth() const
123     {
124         return 0;
125     }
126 
IsZero()127     virtual bool IsZero() const
128     {
129         return false;
130     }
131 
IsIntZero()132     virtual bool IsIntZero() const
133     {
134         return false;
135     }
136 
IsUseSameSymbol(const MeExpr & expr)137     virtual bool IsUseSameSymbol(const MeExpr &expr) const
138     {
139         return exprID == expr.exprID;
140     }
141 
142     virtual BaseNode &EmitExpr(SSATab &) = 0;
IsLeaf()143     bool IsLeaf() const
144     {
145         return numOpnds == 0;
146     }
147 
IsScalar()148     bool IsScalar() const
149     {
150         return meOp == kMeOpVar || meOp == kMeOpReg;
151     }
152 
IsGcmalloc()153     bool IsGcmalloc() const
154     {
155         return op == OP_gcmalloc || op == OP_gcmallocjarray || op == OP_gcpermalloc || op == OP_gcpermallocjarray;
156     }
157 
IsVolatile()158     virtual bool IsVolatile() const
159     {
160         return false;
161     }
162 
163     bool IsTheSameWorkcand(const MeExpr &) const;
SetDefByStmt(MeStmt &)164     virtual void SetDefByStmt(MeStmt &) {}
165 
GetOpnd(size_t)166     virtual MeExpr *GetOpnd(size_t) const
167     {
168         return nullptr;
169     }
170 
SetOpnd(size_t,MeExpr *)171     virtual void SetOpnd(size_t, MeExpr *)
172     {
173         DEBUG_ASSERT(false, "Should not reach here");
174     }
175 
GetIdenticalExpr(MeExpr &,bool)176     virtual MeExpr *GetIdenticalExpr(MeExpr &, bool) const
177     {
178         DEBUG_ASSERT(false, "Should not reach here");
179         return nullptr;
180     }
181 
GetType()182     virtual MIRType *GetType() const
183     {
184         return nullptr;
185     }
186 
187     // in the expression; nullptr otherwise
188     bool SymAppears(OStIdx oidx);  // check if symbol appears in the expression
189     bool HasIvar() const;          // whether there is any iread node in the expression
Pure()190     bool Pure() const
191     {
192         return !kOpcodeInfo.NotPure(op);
193     }
194 
195     virtual bool IsSameVariableValue(const VarMeExpr &) const;
196     MeExpr *ResolveMeExprValue();
197     bool IsAllOpndsIdentical(const MeExpr &meExpr) const;
GetHashIndex()198     virtual uint32 GetHashIndex() const
199     {
200         return 0;
201     }
HasAddressValue()202     virtual bool HasAddressValue()
203     {
204         return false;
205     }
StrengthReducible()206     virtual bool StrengthReducible()
207     {
208         return false;
209     }
SRMultiplier(OriginalSt * ost)210     virtual int64 SRMultiplier(OriginalSt *ost)
211     {
212         (void)ost;
213         return 1;
214     }
215 
IsOpMeExpr()216     virtual bool IsOpMeExpr() const
217     {
218         return false;
219     }
220 
221 protected:
222     MeExpr *FindSymAppearance(OStIdx oidx);  // find the appearance of the symbol
223 
224     Opcode op;
225     PrimType primType;
226     uint8 numOpnds;
227     MeExprOp meOp;
228     int32 exprID;
229     uint32 treeID = 0;  // for bookkeeping purpose during SSAPRE
230     MeExpr *next = nullptr;
231 };
232 
233 enum MeDefBy {
234     kDefByNo,
235     kDefByStmt,
236     kDefByPhi,
237     kDefByChi,
238     kDefByMustDef  // only applies to callassigned and its siblings
239 };
240 
241 class ChiMeNode;      // circular dependency exists, no other choice
242 class MustDefMeNode;  // circular dependency exists, no other choice
243 class IassignMeStmt;  // circular dependency exists, no other choice
244 
245 // base class for VarMeExpr and RegMeExpr
246 class ScalarMeExpr : public MeExpr {
247 public:
ScalarMeExpr(int32 exprid,OriginalSt * origSt,uint32 vidx,MeExprOp meop,Opcode o,PrimType ptyp)248     ScalarMeExpr(int32 exprid, OriginalSt *origSt, uint32 vidx, MeExprOp meop, Opcode o, PrimType ptyp)
249         : MeExpr(exprid, meop, o, ptyp, 0), ost(origSt), vstIdx(vidx), defBy(kDefByNo)
250     {
251         def.defStmt = nullptr;
252     }
253 
254     ~ScalarMeExpr() = default;
255 
IsIdentical(MeExpr &)256     bool IsIdentical(MeExpr &) const
257     {
258         CHECK_FATAL(false, "ScalarMeExpr::IsIdentical() should not be called");
259         return true;
260     }
261 
262     bool IsUseSameSymbol(const MeExpr &) const override;
263 
SetDefByStmt(MeStmt & defStmt)264     void SetDefByStmt(MeStmt &defStmt) override
265     {
266         defBy = kDefByStmt;
267         def.defStmt = &defStmt;
268     }
269 
GetMePhiDef()270     MePhiNode *GetMePhiDef() const
271     {
272         return IsDefByPhi() ? def.defPhi : nullptr;
273     }
274 
IsDefByNo()275     bool IsDefByNo() const
276     {
277         return defBy == kDefByNo;
278     }
279 
IsDefByPhi()280     bool IsDefByPhi() const
281     {
282         return defBy == kDefByPhi;
283     }
284 
IsDefByChi()285     bool IsDefByChi() const
286     {
287         return defBy == kDefByChi;
288     }
289 
IsDefByStmt()290     bool IsDefByStmt() const
291     {
292         return defBy == kDefByStmt;
293     }
294 
IsDefByMustDef()295     bool IsDefByMustDef() const
296     {
297         return defBy == kDefByMustDef;
298     }
299 
300     BB *DefByBB() const;
301 
GetOst()302     OriginalSt *GetOst() const
303     {
304         return ost;
305     }
306 
SetOst(OriginalSt * o)307     void SetOst(OriginalSt *o)
308     {
309         ost = o;
310     }
311 
GetOstIdx()312     OStIdx GetOstIdx() const
313     {
314         return ost->GetIndex();
315     }
316 
GetVstIdx()317     size_t GetVstIdx() const
318     {
319         return vstIdx;
320     }
321 
SetVstIdx(size_t vstIdxVal)322     void SetVstIdx(size_t vstIdxVal)
323     {
324         vstIdx = static_cast<uint32>(vstIdxVal);
325     }
326 
GetDefBy()327     MeDefBy GetDefBy() const
328     {
329         return defBy;
330     }
331 
SetDefBy(MeDefBy defByVal)332     void SetDefBy(MeDefBy defByVal)
333     {
334         defBy = defByVal;
335     }
336 
GetDefStmt()337     MeStmt *GetDefStmt() const
338     {
339         return def.defStmt;
340     }
341 
SetDefStmt(MeStmt * defStmt)342     void SetDefStmt(MeStmt *defStmt)
343     {
344         def.defStmt = defStmt;
345     }
346 
GetDefPhi()347     MePhiNode &GetDefPhi()
348     {
349         return *def.defPhi;
350     }
351 
GetDefPhi()352     const MePhiNode &GetDefPhi() const
353     {
354         return *def.defPhi;
355     }
356 
SetDefPhi(MePhiNode & defPhi)357     void SetDefPhi(MePhiNode &defPhi)
358     {
359         def.defPhi = &defPhi;
360     }
361 
GetDefChi()362     ChiMeNode &GetDefChi()
363     {
364         return *def.defChi;
365     }
366 
GetDefChi()367     const ChiMeNode &GetDefChi() const
368     {
369         return *def.defChi;
370     }
371 
SetDefChi(ChiMeNode & defChi)372     void SetDefChi(ChiMeNode &defChi)
373     {
374         def.defChi = &defChi;
375     }
376 
GetDefMustDef()377     MustDefMeNode &GetDefMustDef()
378     {
379         return *def.defMustDef;
380     }
381 
GetDefMustDef()382     const MustDefMeNode &GetDefMustDef() const
383     {
384         return *def.defMustDef;
385     }
386 
SetDefMustDef(MustDefMeNode & defMustDef)387     void SetDefMustDef(MustDefMeNode &defMustDef)
388     {
389         def.defMustDef = &defMustDef;
390     }
391 
GetRegIdx()392     PregIdx GetRegIdx() const
393     {
394         DEBUG_ASSERT(ost->IsPregOst(), "GetPregIdx: not a preg");
395         return ost->GetPregIdx();
396     }
397 
IsNormalReg()398     bool IsNormalReg() const
399     {
400         DEBUG_ASSERT(ost->IsPregOst(), "GetPregIdx: not a preg");
401         return ost->GetPregIdx() >= 0;
402     }
403 
404     MeStmt *GetDefByMeStmt() const;
405     BB *GetDefByBBMeStmt(const Dominance &, MeStmtPtr &) const;
406     void Dump(const IRMap *, int32 indent = 0) const override;
407     BaseNode &EmitExpr(SSATab &) override;
408     bool IsSameVariableValue(const VarMeExpr &) const override;
409     ScalarMeExpr *FindDefByStmt(std::set<ScalarMeExpr *> &visited);
410     bool IsZeroVersion() const;
411 
412 protected:
413     OriginalSt *ost;
414     uint32 vstIdx;  // the index in MEOptimizer's VersionStTable, 0 if not in VersionStTable
415     MeDefBy defBy : 3;
416     union {
417         MeStmt *defStmt;  // definition stmt of this var
418         MePhiNode *defPhi;
419         ChiMeNode *defChi;          // definition node by Chi
420         MustDefMeNode *defMustDef;  // definition by callassigned
421     } def;
422 };
423 
424 using RegMeExpr = ScalarMeExpr;
425 
426 // represant dread
427 class VarMeExpr final : public ScalarMeExpr {
428 public:
VarMeExpr(int32 exprid,OriginalSt * ost,size_t vidx,PrimType ptyp)429     VarMeExpr(int32 exprid, OriginalSt *ost, size_t vidx, PrimType ptyp)
430         : ScalarMeExpr(exprid, ost, vidx, kMeOpVar, OP_dread, ptyp)
431     {
432     }
433 
434     ~VarMeExpr() = default;
435 
436     void Dump(const IRMap *, int32 indent = 0) const override;
437     BaseNode &EmitExpr(SSATab &) override;
438     bool IsValidVerIdx(const SSATab &ssaTab) const;
439 
440     bool IsVolatile() const override;
441     // indicate if the variable is local variable but not a function formal variable
442     bool IsPureLocal(const MIRFunction &) const;
443     bool IsSameVariableValue(const VarMeExpr &) const override;
444     VarMeExpr &ResolveVarMeValue();
445     bool PointsToStringLiteral();
446 
GetFieldID()447     FieldID GetFieldID() const
448     {
449         return GetOst()->GetFieldID();
450     }
451 
GetInferredTyIdx()452     TyIdx GetInferredTyIdx() const
453     {
454         return inferredTyIdx;
455     }
456 
SetInferredTyIdx(TyIdx inferredTyIdxVal)457     void SetInferredTyIdx(TyIdx inferredTyIdxVal)
458     {
459         inferredTyIdx = inferredTyIdxVal;
460     }
GetMaybeNull()461     bool GetMaybeNull() const
462     {
463         return maybeNull;
464     }
465 
SetMaybeNull(bool maybeNullVal)466     void SetMaybeNull(bool maybeNullVal)
467     {
468         maybeNull = maybeNullVal;
469     }
470 
GetNoDelegateRC()471     bool GetNoDelegateRC() const
472     {
473         return noDelegateRC;
474     }
475 
SetNoDelegateRC(bool noDelegateRCVal)476     void SetNoDelegateRC(bool noDelegateRCVal)
477     {
478         noDelegateRC = noDelegateRCVal;
479     }
480 
GetNoSubsumeRC()481     bool GetNoSubsumeRC() const
482     {
483         return noSubsumeRC;
484     }
485 
SetNoSubsumeRC(bool noSubsumeRCVal)486     void SetNoSubsumeRC(bool noSubsumeRCVal)
487     {
488         noSubsumeRC = noSubsumeRCVal;
489     }
490 
GetType()491     MIRType *GetType() const override
492     {
493         return GlobalTables::GetTypeTable().GetTypeFromTyIdx(ost->GetTyIdx());
494     }
495 
HasAddressValue()496     bool HasAddressValue() override
497     {
498         return MustBeAddress(GetPrimType()) || GetType()->GetKind() == kTypePointer;
499     }
500 
501 private:
502     bool noDelegateRC = false;  // true if this cannot be optimized by delegaterc
503     bool noSubsumeRC = false;   // true if this cannot be optimized by subsumrc
504     TyIdx inferredTyIdx {0};    /* Non zero if it has a known type (allocation type is seen). */
505     bool maybeNull = true;      // false if definitely not null
506 };
507 
508 class MePhiNode {
509 public:
MePhiNode(MapleAllocator * alloc)510     explicit MePhiNode(MapleAllocator *alloc) : opnds(kOperandNumBinary, nullptr, alloc->Adapter())
511     {
512         opnds.pop_back();
513         opnds.pop_back();
514     }
515 
MePhiNode(ScalarMeExpr * expr,MapleAllocator * alloc)516     MePhiNode(ScalarMeExpr *expr, MapleAllocator *alloc)
517         : lhs(expr), opnds(kOperandNumBinary, nullptr, alloc->Adapter())
518     {
519         expr->SetDefPhi(*this);
520         expr->SetDefBy(kDefByPhi);
521         opnds.pop_back();
522         opnds.pop_back();
523     }
524 
525     ~MePhiNode() = default;
526 
UpdateLHS(ScalarMeExpr & expr)527     void UpdateLHS(ScalarMeExpr &expr)
528     {
529         lhs = &expr;
530         expr.SetDefBy(kDefByPhi);
531         expr.SetDefPhi(*this);
532     }
533 
534     void Dump(const IRMap *irMap) const;
535 
GetOpnd(size_t idx)536     ScalarMeExpr *GetOpnd(size_t idx) const
537     {
538         DEBUG_ASSERT(idx < opnds.size(), "out of range in MeVarPhiNode::GetOpnd");
539         return opnds.at(idx);
540     }
541 
SetOpnd(size_t idx,ScalarMeExpr * opnd)542     void SetOpnd(size_t idx, ScalarMeExpr *opnd)
543     {
544         CHECK_FATAL(idx < opnds.size(), "out of range in MePhiNode::SetOpnd");
545         opnds[idx] = opnd;
546     }
547 
GetOpnds()548     const MapleVector<ScalarMeExpr *> &GetOpnds() const
549     {
550         return opnds;
551     }
552 
GetOpnds()553     MapleVector<ScalarMeExpr *> &GetOpnds()
554     {
555         return opnds;
556     }
557 
SetIsLive(bool isLiveVal)558     void SetIsLive(bool isLiveVal)
559     {
560         isLive = isLiveVal;
561     }
562 
GetIsLive()563     bool GetIsLive() const
564     {
565         return isLive;
566     }
567 
SetDefBB(BB * defBBVal)568     void SetDefBB(BB *defBBVal)
569     {
570         defBB = defBBVal;
571     }
572 
GetDefBB()573     BB *GetDefBB()
574     {
575         return defBB;
576     }
577 
GetDefBB()578     const BB *GetDefBB() const
579     {
580         return defBB;
581     }
582 
GetLHS()583     ScalarMeExpr *GetLHS()
584     {
585         return lhs;
586     }
587 
SetLHS(ScalarMeExpr * value)588     void SetLHS(ScalarMeExpr *value)
589     {
590         value->SetDefBy(kDefByPhi);
591         value->SetDefPhi(*this);
592         lhs = value;
593     }
594 
SetPiAdded()595     void SetPiAdded()
596     {
597         isPiAdded = true;
598     }
599 
IsPiAdded()600     bool IsPiAdded() const
601     {
602         return isPiAdded;
603     }
604 
UseReg()605     bool UseReg() const
606     {
607         return lhs->GetMeOp() == kMeOpReg;
608     }
609 
610 private:
611     ScalarMeExpr *lhs = nullptr;
612     MapleVector<ScalarMeExpr *> opnds;
613     bool isLive = true;
614     BB *defBB = nullptr;  // the bb that defines this phi
615     bool isPiAdded = false;
616 };
617 
618 class ConstMeExpr : public MeExpr {
619 public:
ConstMeExpr(int32 exprID,MIRConst * constValParam,PrimType t)620     ConstMeExpr(int32 exprID, MIRConst *constValParam, PrimType t)
621         : MeExpr(exprID, kMeOpConst, OP_constval, t, 0), constVal(constValParam)
622     {
623     }
624 
625     ~ConstMeExpr() = default;
626 
627     void Dump(const IRMap *, int32 indent = 0) const override;
628     BaseNode &EmitExpr(SSATab &) override;
629     bool GeZero() const;
630     bool GtZero() const;
631     bool IsZero() const override;
632     bool IsIntZero() const override;
633     bool IsOne() const;
634     // Get int value represented by IntVal class
635     IntVal GetIntValue() const;
636     // Get value extended by its sign
637     int64 GetExtIntValue() const;
638     // Get zero extended value
639     uint64 GetZXTIntValue() const;
640     // Get sign extended value
641     int64 GetSXTIntValue() const;
642 
GetConstVal()643     MIRConst *GetConstVal()
644     {
645         return constVal;
646     }
647 
GetConstVal()648     const MIRConst *GetConstVal() const
649     {
650         return constVal;
651     }
652 
653     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
654 
GetHashIndex()655     uint32 GetHashIndex() const override
656     {
657         CHECK_FATAL(constVal != nullptr, "constVal is null");
658         if (constVal->GetKind() == kConstInt) {
659             auto *intConst = safe_cast<MIRIntConst>(constVal);
660             CHECK_NULL_FATAL(intConst);
661             return intConst->GetExtValue();
662         }
663         if (constVal->GetKind() == kConstFloatConst) {
664             auto *floatConst = safe_cast<MIRFloatConst>(constVal);
665             CHECK_NULL_FATAL(floatConst);
666             return floatConst->GetIntValue();
667         }
668         if (constVal->GetKind() == kConstDoubleConst) {
669             auto *doubleConst = safe_cast<MIRDoubleConst>(constVal);
670             CHECK_NULL_FATAL(doubleConst);
671             return doubleConst->GetIntValue();
672         }
673         if (constVal->GetKind() == kConstLblConst) {
674             auto *lblConst = safe_cast<MIRLblConst>(constVal);
675             CHECK_NULL_FATAL(lblConst);
676             return lblConst->GetValue();
677         }
678         DEBUG_ASSERT(false, "ComputeHash: const type not yet implemented");
679         return 0;
680     }
681 
682 private:
683     MIRConst *constVal;
684 };
685 
686 class ConststrMeExpr : public MeExpr {
687 public:
ConststrMeExpr(int32 exprID,UStrIdx idx,PrimType t)688     ConststrMeExpr(int32 exprID, UStrIdx idx, PrimType t)
689         : MeExpr(exprID, kMeOpConststr, OP_conststr, t, 0), strIdx(idx)
690     {
691     }
692 
693     ~ConststrMeExpr() = default;
694 
695     void Dump(const IRMap *, int32 indent = 0) const override;
696     BaseNode &EmitExpr(SSATab &) override;
697     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
698 
GetStrIdx()699     UStrIdx GetStrIdx() const
700     {
701         return strIdx;
702     }
703 
GetHashIndex()704     uint32 GetHashIndex() const override
705     {
706         constexpr uint32 kConststrHashShift = 6;
707         return static_cast<uint32>(strIdx) << kConststrHashShift;
708     }
709 
710 private:
711     UStrIdx strIdx;
712 };
713 
714 class Conststr16MeExpr : public MeExpr {
715 public:
Conststr16MeExpr(int32 exprID,U16StrIdx idx,PrimType t)716     Conststr16MeExpr(int32 exprID, U16StrIdx idx, PrimType t)
717         : MeExpr(exprID, kMeOpConststr16, OP_conststr16, t, 0), strIdx(idx)
718     {
719     }
720 
721     ~Conststr16MeExpr() = default;
722 
723     void Dump(const IRMap *, int32 indent = 0) const override;
724     BaseNode &EmitExpr(SSATab &) override;
725     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
726 
GetStrIdx()727     U16StrIdx GetStrIdx()
728     {
729         return strIdx;
730     }
731 
GetHashIndex()732     uint32 GetHashIndex() const override
733     {
734         constexpr uint32 kConststr16HashShift = 6;
735         return static_cast<uint32>(strIdx) << kConststr16HashShift;
736     }
737 
738 private:
739     U16StrIdx strIdx;
740 };
741 
742 class SizeoftypeMeExpr : public MeExpr {
743 public:
SizeoftypeMeExpr(int32 exprid,PrimType t,TyIdx idx)744     SizeoftypeMeExpr(int32 exprid, PrimType t, TyIdx idx)
745         : MeExpr(exprid, kMeOpSizeoftype, OP_sizeoftype, t, 0), tyIdx(idx)
746     {
747     }
748 
749     ~SizeoftypeMeExpr() = default;
750 
751     void Dump(const IRMap *, int32 indent = 0) const override;
752     BaseNode &EmitExpr(SSATab &) override;
753     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
754 
GetTyIdx()755     TyIdx GetTyIdx() const
756     {
757         return tyIdx;
758     }
759 
GetHashIndex()760     uint32 GetHashIndex() const override
761     {
762         constexpr uint32 sizeoftypeHashShift = 5;
763         return static_cast<uint32>(tyIdx) << sizeoftypeHashShift;
764     }
765 
766 private:
767     TyIdx tyIdx;
768 };
769 
770 class FieldsDistMeExpr : public MeExpr {
771 public:
FieldsDistMeExpr(int32 exprid,PrimType t,TyIdx idx,FieldID f1,FieldID f2)772     FieldsDistMeExpr(int32 exprid, PrimType t, TyIdx idx, FieldID f1, FieldID f2)
773         : MeExpr(exprid, kMeOpFieldsDist, OP_fieldsdist, t, 0), tyIdx(idx), fieldID1(f1), fieldID2(f2)
774     {
775     }
776 
777     ~FieldsDistMeExpr() = default;
778     void Dump(const IRMap *, int32 indent = 0) const override;
779     BaseNode &EmitExpr(SSATab &) override;
780     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
781 
GetTyIdx()782     TyIdx GetTyIdx() const
783     {
784         return tyIdx;
785     }
786 
GetFieldID1()787     FieldID GetFieldID1() const
788     {
789         return fieldID1;
790     }
791 
GetFieldID2()792     FieldID GetFieldID2() const
793     {
794         return fieldID2;
795     }
796 
GetHashIndex()797     uint32 GetHashIndex() const override
798     {
799         constexpr uint32 kFieldsDistHashShift = 5;
800         constexpr uint32 kTyIdxShiftFactor = 10;
801         return (static_cast<uint32>(tyIdx) << kTyIdxShiftFactor) +
802                (static_cast<uint32>(fieldID1) << kFieldsDistHashShift) + fieldID2;
803     }
804 
805 private:
806     TyIdx tyIdx;
807     FieldID fieldID1;
808     FieldID fieldID2;
809 };
810 
811 class AddrofMeExpr : public MeExpr {
812 public:
AddrofMeExpr(int32 exprid,PrimType t,OStIdx idx)813     AddrofMeExpr(int32 exprid, PrimType t, OStIdx idx)
814         : MeExpr(exprid, kMeOpAddrof, OP_addrof, t, 0), ostIdx(idx), fieldID(0)
815     {
816     }
817 
818     ~AddrofMeExpr() = default;
819 
820     void Dump(const IRMap *, int32 indent = 0) const override;
821     bool IsUseSameSymbol(const MeExpr &) const override;
822     BaseNode &EmitExpr(SSATab &) override;
823     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
824 
GetOstIdx()825     OStIdx GetOstIdx() const
826     {
827         return ostIdx;
828     }
829 
GetFieldID()830     FieldID GetFieldID() const
831     {
832         return fieldID;
833     }
834 
SetFieldID(FieldID fieldIDVal)835     void SetFieldID(FieldID fieldIDVal)
836     {
837         fieldID = fieldIDVal;
838     }
839 
GetHashIndex()840     uint32 GetHashIndex() const override
841     {
842         constexpr uint32 addrofHashShift = 4;
843         return static_cast<uint32>(ostIdx) << addrofHashShift;
844     }
845 
HasAddressValue()846     bool HasAddressValue() override
847     {
848         return true;
849     }
850 
851 private:
852     OStIdx ostIdx;  // the index in MEOptimizer: OriginalStTable;
853     FieldID fieldID;
854 };
855 
856 class AddroffuncMeExpr : public MeExpr {
857 public:
AddroffuncMeExpr(int32 exprID,PUIdx puIdx)858     AddroffuncMeExpr(int32 exprID, PUIdx puIdx)
859         : MeExpr(exprID, kMeOpAddroffunc, OP_addroffunc, PTY_ptr, 0), puIdx(puIdx)
860     {
861     }
862 
863     ~AddroffuncMeExpr() = default;
864 
865     void Dump(const IRMap *, int32 indent = 0) const override;
866     BaseNode &EmitExpr(SSATab &) override;
867     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
868 
GetPuIdx()869     PUIdx GetPuIdx() const
870     {
871         return puIdx;
872     }
873 
GetHashIndex()874     uint32 GetHashIndex() const override
875     {
876         constexpr uint32 addroffuncHashShift = 5;
877         return puIdx << addroffuncHashShift;
878     }
879 
GetType()880     MIRType *GetType() const override
881     {
882         MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
883         return GlobalTables::GetTypeTable().GetOrCreatePointerType(*func->GetMIRFuncType(), PTY_ptr);
884     }
885 
886 private:
887     PUIdx puIdx;
888 };
889 
890 class AddroflabelMeExpr : public MeExpr {
891 public:
892     LabelIdx labelIdx;
893 
AddroflabelMeExpr(int32 exprid,LabelIdx lidx)894     AddroflabelMeExpr(int32 exprid, LabelIdx lidx)
895         : MeExpr(exprid, kMeOpAddroflabel, OP_addroflabel, PTY_ptr, 0), labelIdx(lidx)
896     {
897     }
898 
~AddroflabelMeExpr()899     ~AddroflabelMeExpr() {}
900 
901     void Dump(const IRMap *, int32 indent = 0) const override;
IsIdentical(const MeExpr * meexpr)902     bool IsIdentical(const MeExpr *meexpr) const
903     {
904         if (meexpr->GetOp() != GetOp()) {
905             return false;
906         }
907         const AddroflabelMeExpr *x = static_cast<const AddroflabelMeExpr *>(meexpr);
908         if (labelIdx != x->labelIdx) {
909             return false;
910         }
911         return true;
912     }
913     BaseNode &EmitExpr(SSATab &) override;
914     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
915 
GetHashIndex()916     uint32 GetHashIndex() const override
917     {
918         constexpr uint32 shiftNum = 4;
919         return labelIdx << shiftNum;
920     }
921 };
922 
923 class GcmallocMeExpr : public MeExpr {
924 public:
GcmallocMeExpr(int32 exprid,Opcode o,PrimType t,TyIdx tyid)925     GcmallocMeExpr(int32 exprid, Opcode o, PrimType t, TyIdx tyid) : MeExpr(exprid, kMeOpGcmalloc, o, t, 0), tyIdx(tyid)
926     {
927     }
928 
929     ~GcmallocMeExpr() = default;
930 
931     void Dump(const IRMap *, int32 indent = 0) const;
932     BaseNode &EmitExpr(SSATab &);
933 
GetTyIdx()934     TyIdx GetTyIdx() const
935     {
936         return tyIdx;
937     }
938 
GetHashIndex()939     uint32 GetHashIndex() const
940     {
941         constexpr uint32 kGcmallocHashShift = 4;
942         return static_cast<uint32>(tyIdx) << kGcmallocHashShift;
943     }
944 
945 private:
946     TyIdx tyIdx;
947 };
948 
949 class OpMeExpr : public MeExpr {
950 public:
OpMeExpr(int32 exprID,Opcode o,PrimType t,size_t n)951     OpMeExpr(int32 exprID, Opcode o, PrimType t, size_t n) : MeExpr(exprID, kMeOpOp, o, t, n), tyIdx(TyIdx(0)) {}
952 
953     // unary
OpMeExpr(int32 exprID,Opcode o,PrimType t,MeExpr * opnd0)954     OpMeExpr(int32 exprID, Opcode o, PrimType t, MeExpr *opnd0) : MeExpr(exprID, kMeOpOp, o, t, 1), tyIdx(TyIdx(0))
955     {
956         SetOpnd(0, opnd0);
957     }
958 
959     // binary
960     OpMeExpr(int32 exprID, Opcode o, PrimType t, MeExpr *opnd0, MeExpr *opnd1, bool order = true)
961         : MeExpr(exprID, kMeOpOp, o, t, 2), tyIdx(TyIdx(0)) // 2 operand
962     {
963         if (order == true) {
964             SetOpnd(0, opnd0);
965             SetOpnd(1, opnd1);
966         } else {
967             SetOpnd(0, opnd1);
968             SetOpnd(1, opnd0);
969         }
970         hasAddressValue = opnd0->HasAddressValue() || opnd1->HasAddressValue();
971     }
972 
OpMeExpr(const OpMeExpr & opMeExpr,int32 exprID)973     OpMeExpr(const OpMeExpr &opMeExpr, int32 exprID)
974         : MeExpr(exprID, kMeOpOp, opMeExpr.GetOp(), opMeExpr.GetPrimType(), opMeExpr.GetNumOpnds()),
975           opnds(opMeExpr.opnds),
976           opndType(opMeExpr.opndType),
977           bitsOffset(opMeExpr.bitsOffset),
978           bitsSize(opMeExpr.bitsSize),
979           depth(opMeExpr.depth),
980           tyIdx(opMeExpr.tyIdx),
981           fieldID(opMeExpr.fieldID),
982           hasAddressValue(opMeExpr.hasAddressValue)
983     {
984     }
985 
986     ~OpMeExpr() = default;
987 
988     OpMeExpr(const OpMeExpr &) = delete;
989     OpMeExpr &operator=(const OpMeExpr &) = delete;
990 
991     bool IsIdentical(const OpMeExpr &meexpr) const;
992     bool IsAllOpndsIdentical(const OpMeExpr &meExpr) const;
993     bool IsCompareIdentical(const OpMeExpr &meExpr) const;
994     void Dump(const IRMap *, int32 indent = 0) const override;
995     bool IsUseSameSymbol(const MeExpr &) const override;
996     MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
997     BaseNode &EmitExpr(SSATab &) override;
GetDepth()998     uint8 GetDepth() const override
999     {
1000         return depth;
1001     }
GetOpnd(size_t i)1002     MeExpr *GetOpnd(size_t i) const override
1003     {
1004         CHECK_FATAL(i < kOperandNumTernary, "OpMeExpr cannot have more than 3 operands");
1005         return opnds[i];
1006     }
1007 
SetOpnd(size_t idx,MeExpr * x)1008     void SetOpnd(size_t idx, MeExpr *x) override
1009     {
1010         CHECK_FATAL(idx < kOperandNumTernary, "out of range in  OpMeExpr::SetOpnd");
1011         opnds[idx] = x;
1012         if (depth <= x->GetDepth()) {
1013             depth = x->GetDepth();
1014             if (depth != UINT8_MAX) {
1015                 depth++;
1016             }
1017         }
1018     }
1019 
GetOpndType()1020     PrimType GetOpndType()
1021     {
1022         return opndType;
1023     }
1024 
GetOpndType()1025     PrimType GetOpndType() const
1026     {
1027         return opndType;
1028     }
1029 
SetOpndType(PrimType opndTypeVal)1030     void SetOpndType(PrimType opndTypeVal)
1031     {
1032         opndType = opndTypeVal;
1033     }
1034 
GetBitsOffSet()1035     uint8 GetBitsOffSet() const
1036     {
1037         return bitsOffset;
1038     }
1039 
SetBitsOffSet(uint8 bitsOffSetVal)1040     void SetBitsOffSet(uint8 bitsOffSetVal)
1041     {
1042         bitsOffset = bitsOffSetVal;
1043     }
1044 
GetBitsSize()1045     uint8 GetBitsSize() const
1046     {
1047         return bitsSize;
1048     }
1049 
SetBitsSize(uint8 bitsSizeVal)1050     void SetBitsSize(uint8 bitsSizeVal)
1051     {
1052         bitsSize = bitsSizeVal;
1053     }
1054 
GetTyIdx()1055     TyIdx GetTyIdx() const
1056     {
1057         return tyIdx;
1058     }
1059 
SetTyIdx(TyIdx tyIdxVal)1060     void SetTyIdx(TyIdx tyIdxVal)
1061     {
1062         tyIdx = tyIdxVal;
1063     }
1064 
GetFieldID()1065     FieldID GetFieldID() const
1066     {
1067         return fieldID;
1068     }
1069 
SetFieldID(FieldID fieldIDVal)1070     void SetFieldID(FieldID fieldIDVal)
1071     {
1072         fieldID = fieldIDVal;
1073     }
1074 
GetHashIndex()1075     uint32 GetHashIndex() const override
1076     {
1077         uint32 hashIdx = static_cast<uint32>(GetOp());
1078         constexpr uint32 kOpMeHashShift = 3;
1079         for (const auto &opnd : opnds) {
1080             if (opnd == nullptr) {
1081                 break;
1082             }
1083             hashIdx += static_cast<uint32>(opnd->GetExprID()) << kOpMeHashShift;
1084         }
1085         return hashIdx;
1086     }
1087 
GetType()1088     MIRType *GetType() const override
1089     {
1090         if (tyIdx != TyIdx(0)) {
1091             return GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
1092         }
1093         return nullptr;
1094     }
SetHasAddressValue()1095     void SetHasAddressValue()
1096     {
1097         if (hasAddressValue) {
1098             return;
1099         }
1100         if (op != OP_select) {
1101             hasAddressValue = opnds[0]->HasAddressValue();
1102             if (!hasAddressValue && numOpnds > 1) {
1103                 hasAddressValue = opnds[1]->HasAddressValue();
1104             }
1105         } else {
1106             hasAddressValue = opnds[1]->HasAddressValue() || opnds[kThirdOpnd]->HasAddressValue();
1107         }
1108     }
HasAddressValue()1109     bool HasAddressValue() override
1110     {
1111         return hasAddressValue || op == OP_iaddrof;
1112     }
1113     bool StrengthReducible() override;
1114     int64 SRMultiplier(OriginalSt *ost) override;
1115 
IsOpMeExpr()1116     bool IsOpMeExpr() const override
1117     {
1118         return true;
1119     }
1120 
1121 private:
1122     std::array<MeExpr *, kOperandNumTernary> opnds = {nullptr};  // kid
1123     PrimType opndType = kPtyInvalid;                             // from type
1124     uint8 bitsOffset = 0;
1125     uint8 bitsSize = 0;
1126     uint8 depth = 0;
1127     TyIdx tyIdx;
1128     FieldID fieldID = 0;  // this is also used to store puIdx
1129 public:
1130     bool hasAddressValue = false;  // used only when op is ADD or SUB
1131 };
1132 
1133 class IvarMeExpr : public MeExpr {
1134 public:
IvarMeExpr(MapleAllocator * alloc,int32 exprid,PrimType t,TyIdx tidx,FieldID fid,Opcode op)1135     IvarMeExpr(MapleAllocator *alloc, int32 exprid, PrimType t, TyIdx tidx, FieldID fid, Opcode op)
1136         : MeExpr(exprid, kMeOpIvar, op, t, 1), tyIdx(tidx), fieldID(fid), muList(1, nullptr, alloc->Adapter())
1137     {
1138     }
1139 
IvarMeExpr(MapleAllocator * alloc,int32 exprid,PrimType t,TyIdx tidx,FieldID fid)1140     IvarMeExpr(MapleAllocator *alloc, int32 exprid, PrimType t, TyIdx tidx, FieldID fid)
1141         : IvarMeExpr(alloc, exprid, t, tidx, fid, OP_iread)
1142     {
1143     }
1144 
IvarMeExpr(MapleAllocator * alloc,int32 exprid,const IvarMeExpr & ivarme)1145     IvarMeExpr(MapleAllocator *alloc, int32 exprid, const IvarMeExpr &ivarme)
1146         : MeExpr(exprid, kMeOpIvar, ivarme.op, ivarme.GetPrimType(), 1),
1147           defStmt(ivarme.defStmt),
1148           base(ivarme.base),
1149           tyIdx(ivarme.tyIdx),
1150           fieldID(ivarme.fieldID),
1151           offset(ivarme.offset),
1152           volatileFromBaseSymbol(ivarme.volatileFromBaseSymbol),
1153           muList(ivarme.muList, alloc->Adapter())
1154     {
1155     }
1156 
1157     IvarMeExpr() = delete;  // Disable default ctor
1158 
1159     ~IvarMeExpr() = default;
1160 
1161     void Dump(const IRMap *, int32 indent = 0) const override;
GetDepth()1162     uint8 GetDepth() const override
1163     {
1164         return base->GetDepth() + 1;
1165     }
1166     BaseNode &EmitExpr(SSATab &) override;
1167     bool IsVolatile() const override;
1168     bool IsFinal();
1169     bool IsRCWeak() const;
1170     bool IsUseSameSymbol(const MeExpr &) const override;
1171     bool IsIdentical(IvarMeExpr &expr, bool inConstructor) const;
1172     bool IsMuListIdentical(IvarMeExpr &expr) const;
1173     MeExpr *GetIdenticalExpr(MeExpr &expr, bool inConstructor) const override;
GetOpnd(size_t)1174     MeExpr *GetOpnd(size_t) const override
1175     {
1176         return base;
1177     }
1178 
GetDefStmt()1179     IassignMeStmt *GetDefStmt() const
1180     {
1181         return defStmt;
1182     }
1183 
SetDefStmt(IassignMeStmt * defStmtPara)1184     void SetDefStmt(IassignMeStmt *defStmtPara)
1185     {
1186         defStmt = defStmtPara;
1187     }
1188 
GetBase()1189     const MeExpr *GetBase() const
1190     {
1191         return base;
1192     }
1193 
GetBase()1194     MeExpr *GetBase()
1195     {
1196         return base;
1197     }
1198 
SetBase(MeExpr * value)1199     void SetBase(MeExpr *value)
1200     {
1201         base = value;
1202     }
1203 
GetTyIdx()1204     TyIdx GetTyIdx() const
1205     {
1206         return tyIdx;
1207     }
1208 
SetTyIdx(TyIdx tyIdxVal)1209     void SetTyIdx(TyIdx tyIdxVal)
1210     {
1211         tyIdx = tyIdxVal;
1212     }
1213 
GetInferredTyIdx()1214     TyIdx GetInferredTyIdx() const
1215     {
1216         return inferredTyIdx;
1217     }
1218 
SetInferredTyidx(TyIdx inferredTyIdxVal)1219     void SetInferredTyidx(TyIdx inferredTyIdxVal)
1220     {
1221         inferredTyIdx = inferredTyIdxVal;
1222     }
1223 
GetFieldID()1224     FieldID GetFieldID() const
1225     {
1226         return fieldID;
1227     }
1228 
SetFieldID(FieldID fieldIDVal)1229     void SetFieldID(FieldID fieldIDVal)
1230     {
1231         fieldID = fieldIDVal;
1232     }
1233 
GetOffset()1234     int32 GetOffset() const
1235     {
1236         return offset;
1237     }
1238 
SetOffset(int32 val)1239     void SetOffset(int32 val)
1240     {
1241         offset = val;
1242     }
1243 
GetMaybeNull()1244     bool GetMaybeNull() const
1245     {
1246         return maybeNull;
1247     }
1248 
SetMaybeNull(bool maybeNullVal)1249     void SetMaybeNull(bool maybeNullVal)
1250     {
1251         maybeNull = maybeNullVal;
1252     }
1253 
GetVolatileFromBaseSymbol()1254     bool GetVolatileFromBaseSymbol() const
1255     {
1256         return volatileFromBaseSymbol;
1257     }
1258 
SetVolatileFromBaseSymbol(bool value)1259     void SetVolatileFromBaseSymbol(bool value)
1260     {
1261         volatileFromBaseSymbol = value;
1262     }
1263 
GetMuList()1264     MapleVector<ScalarMeExpr *> &GetMuList()
1265     {
1266         return muList;
1267     }
1268 
GetMuList()1269     const MapleVector<ScalarMeExpr *> &GetMuList() const
1270     {
1271         return muList;
1272     }
1273 
GetUniqueMu()1274     ScalarMeExpr *GetUniqueMu()
1275     {
1276         CHECK_FATAL(muList.size() == 1, "scalar ivar should has only 1 mu");
1277         return muList[0];
1278     }
1279 
GetUniqueMu()1280     const ScalarMeExpr *GetUniqueMu() const
1281     {
1282         CHECK_FATAL(muList.size() == 1, "scalar ivar should has only 1 mu");
1283         return muList[0];
1284     }
1285 
SetMuItem(size_t i,ScalarMeExpr * muVal)1286     void SetMuItem(size_t i, ScalarMeExpr *muVal)
1287     {
1288         CHECK_FATAL(i < muList.size(), "container check");
1289         muList[i] = muVal;
1290     }
1291 
SetMuList(const MapleVector<ScalarMeExpr * > & inputMuList)1292     void SetMuList(const MapleVector<ScalarMeExpr *> &inputMuList)
1293     {
1294         size_t len = inputMuList.size();
1295         if (muList.size() != len) {
1296             muList.resize(len, nullptr);
1297         }
1298         for (size_t i = 0; i < len; ++i) {
1299             muList[i] = inputMuList[i];
1300         }
1301     }
1302 
SetMuList(const std::vector<ScalarMeExpr * > & inputMuList)1303     void SetMuList(const std::vector<ScalarMeExpr *> &inputMuList)
1304     {
1305         size_t len = inputMuList.size();
1306         if (muList.size() != len) {
1307             muList.resize(len, nullptr);
1308         }
1309         for (size_t i = 0; i < len; ++i) {
1310             muList[i] = inputMuList[i];
1311         }
1312     }
1313 
GetMuCount()1314     uint32 GetMuCount() const
1315     {
1316         return static_cast<uint32>(muList.size());
1317     }
1318 
HasMultipleMu()1319     bool HasMultipleMu() const
1320     {
1321         return muList.size() > 1;
1322     }
1323 
GetHashIndex()1324     uint32 GetHashIndex() const override
1325     {
1326         constexpr uint32 kIvarHashShift = 4;
1327         return static_cast<uint32>(op) + static_cast<uint32>(fieldID) + static_cast<uint32>(offset) +
1328                (static_cast<uint32>(base->GetExprID()) << kIvarHashShift);
1329     }
1330 
GetType()1331     MIRType *GetType() const override
1332     {
1333         MIRPtrType *ptrtype = static_cast<MIRPtrType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx));
1334         if (fieldID == 0) {
1335             return ptrtype->GetPointedType();
1336         }
1337         return GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrtype->GetPointedTyIdxWithFieldID(fieldID));
1338     }
1339 
HasAddressValue()1340     bool HasAddressValue() override
1341     {
1342         return GetType()->GetKind() == kTypePointer;
1343     }
1344 
1345 private:
1346     IassignMeStmt *defStmt = nullptr;
1347     MeExpr *base = nullptr;
1348     TyIdx tyIdx {0};
1349     TyIdx inferredTyIdx {0};  // may be a subclass of above tyIdx
1350     FieldID fieldID = 0;
1351     int32 offset = 0;
1352     bool maybeNull = true;                // false if definitely not null
1353     bool volatileFromBaseSymbol = false;  // volatile due to its base symbol being volatile
1354 public:
1355     bool simplifiedWithConstOffset = false;
1356 
1357 private:
1358     // muList size must be >= 1, can not be empty
1359     MapleVector<ScalarMeExpr *> muList;  // vector type ivar may have multiple mu, non-vector type ivar has only 1 mu
1360 };
1361 
1362 class MeStmt {
1363 public:
MeStmt(const StmtNode * sst)1364     explicit MeStmt(const StmtNode *sst)
1365     {
1366         DEBUG_ASSERT(sst != nullptr, "StmtNode nullptr check");
1367         op = sst->GetOpCode();
1368         srcPos = sst->GetSrcPos();
1369         originalId = sst->GetOriginalID();
1370         meStmtId = sst->GetStmtID();
1371         if (sst->IsInSafeRegion()) {
1372             SetInSafeRegion();
1373         }
1374     }
1375 
MeStmt(Opcode op1)1376     explicit MeStmt(Opcode op1) : op(op1) {}
1377 
1378     virtual ~MeStmt() = default;
1379 
GetIsLive()1380     bool GetIsLive() const
1381     {
1382         return isLive;
1383     }
1384 
SetIsLive(bool value)1385     void SetIsLive(bool value)
1386     {
1387         isLive = value;
1388     }
1389 
1390     virtual void Dump(const IRMap *) const;
1391     MeStmt *GetNextMeStmt() const;
NumMeStmtOpnds()1392     virtual size_t NumMeStmtOpnds() const
1393     {
1394         return 0;
1395     }
1396 
GetOpnd(size_t)1397     virtual MeExpr *GetOpnd(size_t) const
1398     {
1399         return nullptr;
1400     }
1401 
SetOpnd(size_t,MeExpr *)1402     virtual void SetOpnd(size_t, MeExpr *) {}
1403 
IsReturn()1404     bool IsReturn() const
1405     {
1406         return op == OP_gosub || op == OP_retsub || op == OP_throw || op == OP_return;
1407     }
1408 
IsCondBr()1409     bool IsCondBr() const
1410     {
1411         return op == OP_brtrue || op == OP_brfalse;
1412     }
1413 
IsAssign()1414     bool IsAssign() const
1415     {
1416         return op == OP_dassign || op == OP_maydassign || op == OP_iassign || op == OP_regassign || op == OP_piassign;
1417     }
1418 
GetReturnType()1419     virtual MIRType *GetReturnType() const
1420     {
1421         return nullptr;
1422     }
1423 
1424     void EmitCallReturnVector(CallReturnVector &nRets);
GetMustDefList()1425     virtual MapleVector<MustDefMeNode> *GetMustDefList()
1426     {
1427         return nullptr;
1428     }
1429 
GetMustDefList()1430     const virtual MapleVector<MustDefMeNode> &GetMustDefList() const
1431     {
1432         CHECK_FATAL(false, "should be implemented");
1433     }
1434 
GetAssignedLHS()1435     const virtual ScalarMeExpr *GetAssignedLHS() const
1436     {
1437         return nullptr;
1438     }
1439 
GetAssignedLHS()1440     virtual ScalarMeExpr *GetAssignedLHS()
1441     {
1442         return nullptr;
1443     }
1444 
GetChiList()1445     virtual MapleMap<OStIdx, ChiMeNode *> *GetChiList()
1446     {
1447         return nullptr;
1448     }
1449 
GetMuList()1450     virtual MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
1451     {
1452         return nullptr;
1453     }
1454 
CopyBase(const MeStmt & meStmt)1455     void CopyBase(const MeStmt &meStmt)
1456     {
1457         bb = meStmt.bb;
1458         srcPos = meStmt.srcPos;
1459         isLive = meStmt.isLive;
1460         originalId = meStmt.originalId;
1461         meStmtId = meStmt.meStmtId;
1462         stmtAttrs = meStmt.stmtAttrs;
1463     }
1464 
1465     bool IsTheSameWorkcand(const MeStmt &) const;
NeedDecref()1466     virtual bool NeedDecref() const
1467     {
1468         return false;
1469     }
1470 
EnableNeedDecref()1471     virtual void EnableNeedDecref() {}
1472 
DisableNeedDecref()1473     virtual void DisableNeedDecref() {}
1474 
NeedIncref()1475     virtual bool NeedIncref() const
1476     {
1477         return false;
1478     }
1479 
SetNeedIncref(bool)1480     virtual void SetNeedIncref(bool) {}
1481 
EnableNeedIncref()1482     virtual void EnableNeedIncref() {}
1483 
DisableNeedIncref()1484     virtual void DisableNeedIncref() {}
1485 
GetLHS()1486     virtual ScalarMeExpr *GetLHS() const
1487     {
1488         return nullptr;
1489     }
1490 
GetRHS()1491     virtual MeExpr *GetRHS() const
1492     {
1493         return nullptr;
1494     }
1495 
GetVarLHS()1496     virtual ScalarMeExpr *GetVarLHS() const
1497     {
1498         return nullptr;
1499     }
1500 
GetVarLHS()1501     virtual ScalarMeExpr *GetVarLHS()
1502     {
1503         return nullptr;
1504     }
1505 
GetLHSRef(bool)1506     virtual MeExpr *GetLHSRef(bool)
1507     {
1508         return nullptr;
1509     }
1510 
1511     virtual StmtNode &EmitStmt(SSATab &ssaTab);
1512 
RemoveNode()1513     void RemoveNode()
1514     {
1515         // remove this node from the double link list
1516         if (prev != nullptr) {
1517             prev->next = next;
1518         }
1519         if (next != nullptr) {
1520             next->prev = prev;
1521         }
1522     }
1523 
AddNext(MeStmt * node)1524     void AddNext(MeStmt *node)
1525     {
1526         // add node to the next of this list
1527         node->next = next;
1528         node->prev = this;
1529         if (next != nullptr) {
1530             next->prev = node;
1531         }
1532         next = node;
1533     }
1534 
AddPrev(MeStmt * node)1535     void AddPrev(MeStmt *node)
1536     {
1537         // add node to the prev of this list
1538         node->prev = prev;
1539         node->next = this;
1540         if (prev != nullptr) {
1541             prev->next = node;
1542         }
1543         prev = node;
1544     }
1545 
GetBB()1546     const BB *GetBB() const
1547     {
1548         return bb;
1549     }
GetBB()1550     BB *GetBB()
1551     {
1552         return bb;
1553     }
1554 
SetBB(BB * curBB)1555     void SetBB(BB *curBB)
1556     {
1557         bb = curBB;
1558     }
1559 
GetSrcPosition()1560     const SrcPosition &GetSrcPosition() const
1561     {
1562         return srcPos;
1563     }
1564 
SetSrcPos(SrcPosition pos)1565     void SetSrcPos(SrcPosition pos)
1566     {
1567         srcPos = pos;
1568     }
1569 
CopyInfo(const MeStmt & stmt)1570     void CopyInfo(const MeStmt &stmt)
1571     {
1572         this->srcPos = stmt.srcPos;
1573         this->originalId = stmt.originalId;
1574         this->meStmtId = stmt.meStmtId;
1575         this->stmtAttrs = stmt.stmtAttrs;
1576     }
1577 
SetPrev(MeStmt * v)1578     void SetPrev(MeStmt *v)
1579     {
1580         prev = v;
1581     }
1582 
SetNext(MeStmt * n)1583     void SetNext(MeStmt *n)
1584     {
1585         next = n;
1586     }
1587 
GetPrev()1588     MeStmt *GetPrev() const
1589     {
1590         return prev;
1591     }
1592 
GetNext()1593     MeStmt *GetNext() const
1594     {
1595         return next;
1596     }
1597 
GetOp()1598     Opcode GetOp() const
1599     {
1600         return op;
1601     }
1602 
SetOp(Opcode currOp)1603     void SetOp(Opcode currOp)
1604     {
1605         op = currOp;
1606     }
1607 
GetOriginalId()1608     uint32 GetOriginalId() const
1609     {
1610         return originalId;
1611     }
1612 
SetOriginalId(uint32 id)1613     void SetOriginalId(uint32 id)
1614     {
1615         originalId = id;
1616     }
1617 
GetMeStmtId()1618     uint32 GetMeStmtId() const
1619     {
1620         return meStmtId;
1621     }
1622 
SetMeStmtId(uint32 id)1623     void SetMeStmtId(uint32 id)
1624     {
1625         meStmtId = id;
1626     }
1627 
IsInSafeRegion()1628     bool IsInSafeRegion() const
1629     {
1630         return stmtAttrs.GetAttr(STMTATTR_insaferegion);
1631     }
1632 
SetInSafeRegion()1633     void SetInSafeRegion()
1634     {
1635         stmtAttrs.SetAttr(STMTATTR_insaferegion);
1636     }
1637 
CopySafeRegionAttr(const StmtAttrs & stmtAttr)1638     void CopySafeRegionAttr(const StmtAttrs &stmtAttr)
1639     {
1640         this->stmtAttrs.AppendAttr(stmtAttr.GetTargetAttrFlag(STMTATTR_insaferegion));
1641     }
1642 
GetStmtAttr()1643     const StmtAttrs &GetStmtAttr() const
1644     {
1645         return stmtAttrs;
1646     }
1647 
1648 protected:
1649     StmtAttrs stmtAttrs;
1650 
1651 private:
1652     uint32 originalId = 0xdeadbeef;
1653     uint32 meStmtId = 0xdeadbeef;
1654     Opcode op;
1655     bool isLive = true;
1656     BB *bb = nullptr;
1657     SrcPosition srcPos;
1658     MeStmt *prev = nullptr;
1659     MeStmt *next = nullptr;
1660 };
1661 
1662 class ChiMeNode {
1663 public:
ChiMeNode(MeStmt * meStmt)1664     explicit ChiMeNode(MeStmt *meStmt) : base(meStmt) {}
1665 
1666     ~ChiMeNode() = default;
1667 
GetIsLive()1668     bool GetIsLive() const
1669     {
1670         return isLive;
1671     }
1672 
SetIsLive(bool value)1673     void SetIsLive(bool value)
1674     {
1675         isLive = value;
1676     }
1677 
GetRHS()1678     ScalarMeExpr *GetRHS()
1679     {
1680         return rhs;
1681     }
1682 
GetRHS()1683     const ScalarMeExpr *GetRHS() const
1684     {
1685         return rhs;
1686     }
1687 
SetRHS(ScalarMeExpr * value)1688     void SetRHS(ScalarMeExpr *value)
1689     {
1690         rhs = value;
1691     }
1692 
GetLHS()1693     ScalarMeExpr *GetLHS() const
1694     {
1695         return lhs;
1696     }
1697 
SetLHS(ScalarMeExpr * value)1698     void SetLHS(ScalarMeExpr *value)
1699     {
1700         lhs = value;
1701     }
1702 
1703     void Dump(const IRMap *irMap) const;
1704 
GetBase()1705     MeStmt *GetBase() const
1706     {
1707         return base;
1708     }
1709 
SetBase(MeStmt * value)1710     void SetBase(MeStmt *value)
1711     {
1712         base = value;
1713     }
1714 
1715 private:
1716     ScalarMeExpr *rhs = nullptr;
1717     ScalarMeExpr *lhs = nullptr;
1718     MeStmt *base;
1719     bool isLive = true;
1720 };
1721 
1722 class MustDefMeNode {
1723 public:
MustDefMeNode(ScalarMeExpr * x,MeStmt * meStmt)1724     MustDefMeNode(ScalarMeExpr *x, MeStmt *meStmt) : lhs(x), base(meStmt)
1725     {
1726         x->SetDefBy(kDefByMustDef);
1727         x->SetDefMustDef(*this);
1728     }
1729 
GetLHS()1730     const ScalarMeExpr *GetLHS() const
1731     {
1732         return lhs;
1733     }
1734 
GetLHS()1735     ScalarMeExpr *GetLHS()
1736     {
1737         return lhs;
1738     }
1739 
SetLHS(ScalarMeExpr * value)1740     void SetLHS(ScalarMeExpr *value)
1741     {
1742         lhs = value;
1743     }
1744 
GetBase()1745     const MeStmt *GetBase() const
1746     {
1747         return base;
1748     }
1749 
GetBase()1750     MeStmt *GetBase()
1751     {
1752         return base;
1753     }
1754 
SetBase(MeStmt * value)1755     void SetBase(MeStmt *value)
1756     {
1757         base = value;
1758     }
1759 
GetIsLive()1760     bool GetIsLive() const
1761     {
1762         return isLive;
1763     }
1764 
SetIsLive(bool value)1765     void SetIsLive(bool value)
1766     {
1767         isLive = value;
1768     }
1769 
MustDefMeNode(const MustDefMeNode & mustDef)1770     MustDefMeNode(const MustDefMeNode &mustDef)
1771     {
1772         lhs = mustDef.lhs;
1773         base = mustDef.base;
1774         isLive = mustDef.isLive;
1775         UpdateLHS(*lhs);
1776     }
1777 
1778     MustDefMeNode &operator=(const MustDefMeNode &mustDef)
1779     {
1780         if (&mustDef != this) {
1781             lhs = mustDef.lhs;
1782             base = mustDef.base;
1783             isLive = mustDef.isLive;
1784             UpdateLHS(*lhs);
1785         }
1786         return *this;
1787     }
1788 
UpdateLHS(ScalarMeExpr & x)1789     void UpdateLHS(ScalarMeExpr &x)
1790     {
1791         lhs = &x;
1792         x.SetDefBy(kDefByMustDef);
1793         x.SetDefMustDef(*this);
1794     }
1795 
1796     ~MustDefMeNode() = default;
1797 
1798     void Dump(const IRMap *) const;
1799 
1800 private:
1801     ScalarMeExpr *lhs;  // could be var or register, can we make this private?
1802     MeStmt *base;
1803     bool isLive = true;
1804 };
1805 
1806 class PiassignMeStmt : public MeStmt {
1807 public:
PiassignMeStmt(MapleAllocator *)1808     explicit PiassignMeStmt(MapleAllocator *) : MeStmt(OP_piassign) {}
1809     ~PiassignMeStmt() = default;
1810 
SetLHS(VarMeExpr & l)1811     void SetLHS(VarMeExpr &l)
1812     {
1813         lhs = &l;
1814     }
1815 
SetRHS(VarMeExpr & r)1816     void SetRHS(VarMeExpr &r)
1817     {
1818         rhs = &r;
1819     }
1820 
SetGeneratedBy(MeStmt & meStmt)1821     void SetGeneratedBy(MeStmt &meStmt)
1822     {
1823         generatedBy = &meStmt;
1824     }
1825 
GetLHS()1826     VarMeExpr *GetLHS() const
1827     {
1828         return lhs;
1829     }
1830 
GetRHS()1831     VarMeExpr *GetRHS() const
1832     {
1833         return rhs;
1834     }
1835 
GetGeneratedBy()1836     MeStmt *GetGeneratedBy() const
1837     {
1838         return generatedBy;
1839     }
1840 
SetIsToken(bool t)1841     void SetIsToken(bool t)
1842     {
1843         isToken = t;
1844     }
1845 
GetIsToken()1846     bool GetIsToken() const
1847     {
1848         return isToken;
1849     }
1850 
1851     void Dump(const IRMap *) const;
1852 
1853 private:
1854     VarMeExpr *rhs = nullptr;
1855     VarMeExpr *lhs = nullptr;
1856     MeStmt *generatedBy = nullptr;
1857     bool isToken = false;
1858 };
1859 
1860 class AssignMeStmt : public MeStmt {
1861 public:
AssignMeStmt(const StmtNode * stt)1862     explicit AssignMeStmt(const StmtNode *stt) : MeStmt(stt) {}
1863 
AssignMeStmt(Opcode op,ScalarMeExpr * theLhs,MeExpr * rhsVal)1864     AssignMeStmt(Opcode op, ScalarMeExpr *theLhs, MeExpr *rhsVal) : MeStmt(op), rhs(rhsVal), lhs(theLhs) {}
1865 
1866     ~AssignMeStmt() = default;
1867 
NumMeStmtOpnds()1868     size_t NumMeStmtOpnds() const
1869     {
1870         return kOperandNumUnary;
1871     }
1872 
GetOpnd(size_t)1873     MeExpr *GetOpnd(size_t) const
1874     {
1875         return rhs;
1876     }
1877 
SetOpnd(size_t,MeExpr * val)1878     void SetOpnd(size_t, MeExpr *val)
1879     {
1880         rhs = val;
1881     }
1882 
1883     void Dump(const IRMap *) const;
1884 
NeedIncref()1885     bool NeedIncref() const
1886     {
1887         return needIncref;
1888     }
1889 
1890     void SetNeedIncref(bool value = true)
1891     {
1892         needIncref = value;
1893     }
1894 
EnableNeedIncref()1895     void EnableNeedIncref()
1896     {
1897         needIncref = true;
1898     }
1899 
DisableNeedIncref()1900     void DisableNeedIncref()
1901     {
1902         needIncref = false;
1903     }
1904 
NeedDecref()1905     bool NeedDecref() const
1906     {
1907         return needDecref;
1908     }
1909 
SetNeedDecref(bool value)1910     void SetNeedDecref(bool value)
1911     {
1912         needDecref = value;
1913     }
1914 
EnableNeedDecref()1915     void EnableNeedDecref()
1916     {
1917         needDecref = true;
1918     }
1919 
DisableNeedDecref()1920     void DisableNeedDecref()
1921     {
1922         needDecref = false;
1923     }
1924 
GetLHS()1925     ScalarMeExpr *GetLHS() const
1926     {
1927         return lhs;
1928     }
1929 
GetRHS()1930     MeExpr *GetRHS() const
1931     {
1932         return rhs;
1933     }
1934 
SetRHS(MeExpr * value)1935     void SetRHS(MeExpr *value)
1936     {
1937         rhs = value;
1938     }
1939 
SetLHS(ScalarMeExpr * value)1940     void SetLHS(ScalarMeExpr *value)
1941     {
1942         lhs = value;
1943     }
1944 
UpdateLhs(ScalarMeExpr * var)1945     void UpdateLhs(ScalarMeExpr *var)
1946     {
1947         lhs = var;
1948         var->SetDefBy(kDefByStmt);
1949         var->SetDefStmt(this);
1950     }
1951 
1952     StmtNode &EmitStmt(SSATab &ssaTab);
1953 
1954 protected:
1955     MeExpr *rhs = nullptr;
1956     ScalarMeExpr *lhs = nullptr;
1957     bool needIncref = false;  // to be determined by analyzerc phase
1958     bool needDecref = false;  // to be determined by analyzerc phase
1959 public:
1960     bool isIncDecStmt = false;  // has the form of an increment or decrement stmt
1961 };
1962 
1963 class DassignMeStmt : public AssignMeStmt {
1964 public:
DassignMeStmt(MapleAllocator * alloc,const StmtNode * stt)1965     DassignMeStmt(MapleAllocator *alloc, const StmtNode *stt)
1966         : AssignMeStmt(stt), chiList(std::less<OStIdx>(), alloc->Adapter())
1967     {
1968     }
1969 
DassignMeStmt(MapleAllocator * alloc,VarMeExpr * theLhs,MeExpr * rhsVal)1970     DassignMeStmt(MapleAllocator *alloc, VarMeExpr *theLhs, MeExpr *rhsVal)
1971         : AssignMeStmt(OP_dassign, theLhs, rhsVal), chiList(std::less<OStIdx>(), alloc->Adapter())
1972     {
1973     }
1974 
DassignMeStmt(MapleAllocator * alloc,const DassignMeStmt * dass)1975     DassignMeStmt(MapleAllocator *alloc, const DassignMeStmt *dass)
1976         : AssignMeStmt(dass->GetOp(), dass->GetLHS(), dass->GetRHS()), chiList(std::less<OStIdx>(), alloc->Adapter())
1977     {
1978     }
1979 
1980     ~DassignMeStmt() = default;
1981 
GetChiList()1982     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
1983     {
1984         return &chiList;
1985     }
1986 
SetChiList(const MapleMap<OStIdx,ChiMeNode * > & value)1987     void SetChiList(const MapleMap<OStIdx, ChiMeNode *> &value)
1988     {
1989         chiList = value;
1990     }
1991 
Propagated()1992     bool Propagated() const
1993     {
1994         return propagated;
1995     }
1996 
SetPropagated(bool value)1997     void SetPropagated(bool value)
1998     {
1999         propagated = value;
2000     }
2001 
GetWasMayDassign()2002     bool GetWasMayDassign() const
2003     {
2004         return wasMayDassign;
2005     }
2006 
SetWasMayDassign(bool value)2007     void SetWasMayDassign(bool value)
2008     {
2009         wasMayDassign = value;
2010     }
2011 
2012     void Dump(const IRMap *) const;
2013 
GetVarLHS()2014     ScalarMeExpr *GetVarLHS() const
2015     {
2016         return static_cast<VarMeExpr *>(lhs);
2017     }
2018 
GetVarLHS()2019     ScalarMeExpr *GetVarLHS()
2020     {
2021         return static_cast<VarMeExpr *>(lhs);
2022     }
2023 
GetOmitEmit()2024     bool GetOmitEmit() const
2025     {
2026         return omitEmit;
2027     }
2028 
SetOmitEmit(bool val)2029     void SetOmitEmit(bool val)
2030     {
2031         omitEmit = val;
2032     }
2033 
GetEmitDassignoff()2034     bool GetEmitDassignoff() const
2035     {
2036         return emitDassignoff;
2037     }
2038 
SetEmitDassignoff(bool val)2039     void SetEmitDassignoff(bool val)
2040     {
2041         emitDassignoff = val;
2042     }
2043 
2044     MeExpr *GetLHSRef(bool excludeLocalRefVar);
2045     StmtNode &EmitStmt(SSATab &ssaTab);
2046 
2047 private:
2048     MapleMap<OStIdx, ChiMeNode *> chiList;
2049     bool propagated = false;      // the RHS has been propagated forward
2050     bool wasMayDassign = false;   // was converted back to dassign by may2dassign phase
2051     bool emitDassignoff = false;  // Emit Iassignoff instead
2052     bool omitEmit = false;        // Skip this stmt instead
2053 };
2054 
2055 class MaydassignMeStmt : public MeStmt {
2056 public:
MaydassignMeStmt(MapleAllocator * alloc,const StmtNode * stt)2057     MaydassignMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2058         : MeStmt(stt), chiList(std::less<OStIdx>(), alloc->Adapter())
2059     {
2060     }
2061 
MaydassignMeStmt(MapleAllocator * alloc,MaydassignMeStmt & maydass)2062     MaydassignMeStmt(MapleAllocator *alloc, MaydassignMeStmt &maydass)
2063         : MeStmt(maydass.GetOp()),
2064           rhs(maydass.GetRHS()),
2065           mayDSSym(maydass.GetMayDassignSym()),
2066           fieldID(maydass.GetFieldID()),
2067           chiList(std::less<OStIdx>(), alloc->Adapter()),
2068           needDecref(maydass.NeedDecref()),
2069           needIncref(maydass.NeedIncref())
2070     {
2071     }
2072 
2073     ~MaydassignMeStmt() = default;
2074 
NumMeStmtOpnds()2075     size_t NumMeStmtOpnds() const
2076     {
2077         return kOperandNumUnary;
2078     }
2079 
GetOpnd(size_t)2080     MeExpr *GetOpnd(size_t) const
2081     {
2082         return rhs;
2083     }
2084 
SetOpnd(size_t,MeExpr * val)2085     void SetOpnd(size_t, MeExpr *val)
2086     {
2087         rhs = val;
2088     }
2089 
GetChiList()2090     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2091     {
2092         return &chiList;
2093     }
2094 
SetChiList(const MapleMap<OStIdx,ChiMeNode * > & value)2095     void SetChiList(const MapleMap<OStIdx, ChiMeNode *> &value)
2096     {
2097         chiList = value;
2098     }
2099 
NeedDecref()2100     bool NeedDecref() const
2101     {
2102         return needDecref;
2103     }
2104 
EnableNeedDecref()2105     void EnableNeedDecref()
2106     {
2107         needDecref = true;
2108     }
2109 
DisableNeedDecref()2110     void DisableNeedDecref()
2111     {
2112         needDecref = false;
2113     }
2114 
NeedIncref()2115     bool NeedIncref() const
2116     {
2117         return needIncref;
2118     }
2119 
2120     void SetNeedIncref(bool val = true)
2121     {
2122         needIncref = val;
2123     }
2124 
EnableNeedIncref()2125     void EnableNeedIncref()
2126     {
2127         needIncref = true;
2128     }
2129 
DisableNeedIncref()2130     void DisableNeedIncref()
2131     {
2132         needIncref = false;
2133     }
2134 
GetMayDassignSym()2135     OriginalSt *GetMayDassignSym()
2136     {
2137         return mayDSSym;
2138     }
2139 
GetMayDassignSym()2140     const OriginalSt *GetMayDassignSym() const
2141     {
2142         return mayDSSym;
2143     }
2144 
SetMayDassignSym(OriginalSt * sym)2145     void SetMayDassignSym(OriginalSt *sym)
2146     {
2147         mayDSSym = sym;
2148     }
2149 
GetFieldID()2150     FieldID GetFieldID() const
2151     {
2152         return fieldID;
2153     }
2154 
SetFieldID(FieldID fieldIDVal)2155     void SetFieldID(FieldID fieldIDVal)
2156     {
2157         fieldID = fieldIDVal;
2158     }
2159 
2160     void Dump(const IRMap *) const;
GetLHS()2161     ScalarMeExpr *GetLHS() const
2162     {
2163         return chiList.find(mayDSSym->GetIndex())->second->GetLHS();
2164     }
2165 
GetRHS()2166     MeExpr *GetRHS() const
2167     {
2168         return rhs;
2169     }
2170 
SetRHS(MeExpr * value)2171     void SetRHS(MeExpr *value)
2172     {
2173         rhs = value;
2174     }
2175 
GetVarLHS()2176     ScalarMeExpr *GetVarLHS() const
2177     {
2178         return chiList.find(mayDSSym->GetIndex())->second->GetLHS();
2179     }
2180 
GetVarLHS()2181     ScalarMeExpr *GetVarLHS()
2182     {
2183         return chiList.find(mayDSSym->GetIndex())->second->GetLHS();
2184     }
2185 
2186     MeExpr *GetLHSRef(bool excludeLocalRefVar);
2187     StmtNode &EmitStmt(SSATab &ssaTab);
2188 
2189 private:
2190     MeExpr *rhs = nullptr;
2191     OriginalSt *mayDSSym = nullptr;
2192     FieldID fieldID = 0;
2193     MapleMap<OStIdx, ChiMeNode *> chiList;
2194     bool needDecref = false;  // to be determined by analyzerc phase
2195     bool needIncref = false;  // to be determined by analyzerc phase
2196 };
2197 
2198 class IassignMeStmt : public MeStmt {
2199 public:
IassignMeStmt(MapleAllocator * alloc,const StmtNode * stt)2200     IassignMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2201         : MeStmt(stt), chiList(std::less<OStIdx>(), alloc->Adapter())
2202     {
2203     }
2204 
IassignMeStmt(MapleAllocator *,const IassignMeStmt & iss)2205     IassignMeStmt(MapleAllocator *, const IassignMeStmt &iss)
2206         : MeStmt(iss), tyIdx(iss.tyIdx), lhsVar(iss.lhsVar), rhs(iss.rhs), chiList(iss.chiList)
2207     {
2208     }
2209 
IassignMeStmt(MapleAllocator *,TyIdx tidx,IvarMeExpr * l,MeExpr * r,const MapleMap<OStIdx,ChiMeNode * > * clist)2210     IassignMeStmt(MapleAllocator *, TyIdx tidx, IvarMeExpr *l, MeExpr *r, const MapleMap<OStIdx, ChiMeNode *> *clist)
2211         : MeStmt(OP_iassign), tyIdx(tidx), lhsVar(l), rhs(r), chiList(*clist)
2212     {
2213         l->SetDefStmt(this);
2214     }
2215 
IassignMeStmt(MapleAllocator * alloc,TyIdx tidx,IvarMeExpr & l,MeExpr & r)2216     IassignMeStmt(MapleAllocator *alloc, TyIdx tidx, IvarMeExpr &l, MeExpr &r)
2217         : MeStmt(OP_iassign), tyIdx(tidx), lhsVar(&l), rhs(&r), chiList(std::less<OStIdx>(), alloc->Adapter())
2218     {
2219         l.SetDefStmt(this);
2220     }
2221 
2222     ~IassignMeStmt() = default;
2223 
GetTyIdx()2224     TyIdx GetTyIdx() const
2225     {
2226         return tyIdx;
2227     }
2228 
SetTyIdx(TyIdx idx)2229     void SetTyIdx(TyIdx idx)
2230     {
2231         tyIdx = idx;
2232     }
2233 
NumMeStmtOpnds()2234     size_t NumMeStmtOpnds() const
2235     {
2236         return kOperandNumBinary;
2237     }
2238 
GetOpnd(size_t idx)2239     MeExpr *GetOpnd(size_t idx) const
2240     {
2241         return idx == 0 ? lhsVar->GetBase() : rhs;
2242     }
2243 
SetOpnd(size_t idx,MeExpr * val)2244     void SetOpnd(size_t idx, MeExpr *val)
2245     {
2246         if (idx == 0) {
2247             lhsVar->SetBase(val);
2248         } else {
2249             rhs = val;
2250         }
2251     }
2252 
GetChiList()2253     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2254     {
2255         return &chiList;
2256     }
GetChiList()2257     const MapleMap<OStIdx, ChiMeNode *> *GetChiList() const
2258     {
2259         return &chiList;
2260     }
2261 
SetChiList(const MapleMap<OStIdx,ChiMeNode * > & value)2262     void SetChiList(const MapleMap<OStIdx, ChiMeNode *> &value)
2263     {
2264         chiList = value;
2265     }
2266 
2267     MeExpr *GetLHSRef(bool excludeLocalRefVar);
NeedDecref()2268     bool NeedDecref() const
2269     {
2270         return needDecref;
2271     }
2272 
EnableNeedDecref()2273     void EnableNeedDecref()
2274     {
2275         needDecref = true;
2276     }
2277 
DisableNeedDecref()2278     void DisableNeedDecref()
2279     {
2280         needDecref = false;
2281     }
2282 
NeedIncref()2283     bool NeedIncref() const
2284     {
2285         return needIncref;
2286     }
2287 
2288     void SetNeedIncref(bool val = true)
2289     {
2290         needIncref = val;
2291     }
2292 
EnableNeedIncref()2293     void EnableNeedIncref()
2294     {
2295         needIncref = true;
2296     }
2297 
DisableNeedIncref()2298     void DisableNeedIncref()
2299     {
2300         needIncref = false;
2301     }
2302 
2303     void Dump(const IRMap *) const;
GetRHS()2304     MeExpr *GetRHS() const
2305     {
2306         return rhs;
2307     }
2308 
SetRHS(MeExpr * val)2309     void SetRHS(MeExpr *val)
2310     {
2311         rhs = val;
2312     }
2313 
GetLHSVal()2314     IvarMeExpr *GetLHSVal() const
2315     {
2316         return lhsVar;
2317     }
2318 
SetLHSVal(IvarMeExpr * val)2319     void SetLHSVal(IvarMeExpr *val)
2320     {
2321         lhsVar = val;
2322         tyIdx = val->GetTyIdx();
2323     }
2324 
GetOmitEmit()2325     bool GetOmitEmit() const
2326     {
2327         return omitEmit;
2328     }
2329 
SetOmitEmit(bool val)2330     void SetOmitEmit(bool val)
2331     {
2332         omitEmit = val;
2333     }
2334 
GetEmitIassignoff()2335     bool GetEmitIassignoff() const
2336     {
2337         return emitIassignoff;
2338     }
2339 
SetEmitIassignoff(bool val)2340     void SetEmitIassignoff(bool val)
2341     {
2342         emitIassignoff = val;
2343     }
2344 
2345     StmtNode &EmitStmt(SSATab &ssaTab);
2346 
2347 private:
2348     TyIdx tyIdx {0};
2349     IvarMeExpr *lhsVar = nullptr;
2350     MeExpr *rhs = nullptr;
2351     MapleMap<OStIdx, ChiMeNode *> chiList;
2352     bool needDecref = false;      // to be determined by analyzerc phase
2353     bool needIncref = false;      // to be determined by analyzerc phase
2354     bool emitIassignoff = false;  // Emit Iassignoff instead
2355     bool omitEmit = false;        // Skip this stmt instead
2356 };
2357 
2358 class NaryMeStmt : public MeStmt {
2359 public:
NaryMeStmt(MapleAllocator * alloc,const StmtNode * stt)2360     NaryMeStmt(MapleAllocator *alloc, const StmtNode *stt) : MeStmt(stt), opnds(alloc->Adapter()) {}
2361 
NaryMeStmt(MapleAllocator * alloc,Opcode op)2362     NaryMeStmt(MapleAllocator *alloc, Opcode op) : MeStmt(op), opnds(alloc->Adapter()) {}
2363 
NaryMeStmt(MapleAllocator * alloc,const NaryMeStmt * nstmt)2364     NaryMeStmt(MapleAllocator *alloc, const NaryMeStmt *nstmt) : MeStmt(nstmt->GetOp()), opnds(alloc->Adapter())
2365     {
2366         for (MeExpr *o : nstmt->opnds) {
2367             opnds.push_back(o);
2368         }
2369     }
2370 
2371     virtual ~NaryMeStmt() = default;
2372 
NumMeStmtOpnds()2373     size_t NumMeStmtOpnds() const
2374     {
2375         return opnds.size();
2376     }
2377 
GetOpnd(size_t idx)2378     MeExpr *GetOpnd(size_t idx) const
2379     {
2380         DEBUG_ASSERT(idx < opnds.size(), "out of range in NaryMeStmt::GetOpnd");
2381         return opnds.at(idx);
2382     }
2383 
SetOpnd(size_t idx,MeExpr * val)2384     void SetOpnd(size_t idx, MeExpr *val)
2385     {
2386         opnds[idx] = val;
2387     }
2388 
GetOpnds()2389     const MapleVector<MeExpr *> &GetOpnds() const
2390     {
2391         return opnds;
2392     }
2393 
PushBackOpnd(MeExpr * val)2394     void PushBackOpnd(MeExpr *val)
2395     {
2396         opnds.push_back(val);
2397     }
2398 
PopBackOpnd()2399     void PopBackOpnd()
2400     {
2401         opnds.pop_back();
2402     }
2403 
SetOpnds(const MapleVector<MeExpr * > & opndsVal)2404     void SetOpnds(const MapleVector<MeExpr *> &opndsVal)
2405     {
2406         opnds = opndsVal;
2407     }
2408 
EraseOpnds(const MapleVector<MeExpr * >::const_iterator begin,const MapleVector<MeExpr * >::const_iterator end)2409     void EraseOpnds(const MapleVector<MeExpr *>::const_iterator begin, const MapleVector<MeExpr *>::const_iterator end)
2410     {
2411         (void)opnds.erase(begin, end);
2412     }
2413 
EraseOpnds(const MapleVector<MeExpr * >::const_iterator it)2414     void EraseOpnds(const MapleVector<MeExpr *>::const_iterator it)
2415     {
2416         (void)opnds.erase(it);
2417     }
2418 
InsertOpnds(const MapleVector<MeExpr * >::const_iterator begin,MeExpr * expr)2419     void InsertOpnds(const MapleVector<MeExpr *>::const_iterator begin, MeExpr *expr)
2420     {
2421         (void)opnds.insert(begin, expr);
2422     }
2423 
2424     void DumpOpnds(const IRMap *) const;
2425     void Dump(const IRMap *) const;
GetMuList()2426     virtual MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
2427     {
2428         return nullptr;
2429     }
2430 
2431     StmtNode &EmitStmt(SSATab &ssaTab);
2432 
2433 private:
2434     MapleVector<MeExpr *> opnds;
2435 };
2436 
2437 class MuChiMePart {
2438 public:
MuChiMePart(MapleAllocator * alloc)2439     explicit MuChiMePart(MapleAllocator *alloc)
2440         : muList(std::less<OStIdx>(), alloc->Adapter()), chiList(std::less<OStIdx>(), alloc->Adapter())
2441     {
2442     }
2443 
GetChiList()2444     virtual MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2445     {
2446         return &chiList;
2447     }
2448 
SetChiList(const MapleMap<OStIdx,ChiMeNode * > & value)2449     void SetChiList(const MapleMap<OStIdx, ChiMeNode *> &value)
2450     {
2451         chiList = value;
2452     }
2453 
2454     virtual ~MuChiMePart() = default;
2455 
2456 protected:
2457     MapleMap<OStIdx, ScalarMeExpr *> muList;
2458     MapleMap<OStIdx, ChiMeNode *> chiList;
2459 };
2460 
2461 class AssignedPart {
2462 public:
AssignedPart(MapleAllocator * alloc)2463     explicit AssignedPart(MapleAllocator *alloc) : mustDefList(alloc->Adapter()) {}
2464 
AssignedPart(MapleAllocator * alloc,MeStmt * defStmt,const MapleVector<MustDefMeNode> & mustDefList)2465     AssignedPart(MapleAllocator *alloc, MeStmt *defStmt, const MapleVector<MustDefMeNode> &mustDefList)
2466         : mustDefList(alloc->Adapter())
2467     {
2468         for (auto &mustDef : mustDefList) {
2469             auto newMustDefNode = alloc->GetMemPool()->New<MustDefMeNode>(mustDef);
2470             newMustDefNode->SetBase(defStmt);
2471             this->mustDefList.push_back(*newMustDefNode);
2472         }
2473     }
2474 
2475     virtual ~AssignedPart() = default;
2476 
2477     void DumpAssignedPart(const IRMap *irMap) const;
2478     VarMeExpr *GetAssignedPartLHSRef(bool excludeLocalRefVar);
2479 
2480 protected:
2481     MapleVector<MustDefMeNode> mustDefList;
2482     bool needDecref = false;  // to be determined by analyzerc phase
2483     bool needIncref = false;  // to be determined by analyzerc phase
2484 };
2485 
2486 class CallMeStmt : public NaryMeStmt, public MuChiMePart, public AssignedPart {
2487 public:
CallMeStmt(MapleAllocator * alloc,const StmtNode * stt)2488     CallMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2489         : NaryMeStmt(alloc, stt),
2490           MuChiMePart(alloc),
2491           AssignedPart(alloc),
2492           puIdx(static_cast<const CallNode *>(stt)->GetPUIdx()),
2493           stmtID(stt->GetStmtID()),
2494           tyIdx(static_cast<const CallNode *>(stt)->GetTyIdx())
2495     {
2496     }
2497 
CallMeStmt(MapleAllocator * alloc,Opcode op)2498     CallMeStmt(MapleAllocator *alloc, Opcode op) : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc) {}
2499 
CallMeStmt(MapleAllocator * alloc,Opcode op,PUIdx idx)2500     CallMeStmt(MapleAllocator *alloc, Opcode op, PUIdx idx)
2501         : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc), puIdx(idx)
2502     {
2503     }
2504 
CallMeStmt(MapleAllocator * alloc,const NaryMeStmt * cstmt,PUIdx idx)2505     CallMeStmt(MapleAllocator *alloc, const NaryMeStmt *cstmt, PUIdx idx)
2506         : NaryMeStmt(alloc, cstmt), MuChiMePart(alloc), AssignedPart(alloc), puIdx(idx)
2507     {
2508     }
2509 
CallMeStmt(MapleAllocator * alloc,const CallMeStmt * cstmt)2510     CallMeStmt(MapleAllocator *alloc, const CallMeStmt *cstmt)
2511         : NaryMeStmt(alloc, cstmt),
2512           MuChiMePart(alloc),
2513           AssignedPart(alloc, this, cstmt->mustDefList),
2514           puIdx(cstmt->GetPUIdx())
2515     {
2516     }
2517 
2518     virtual ~CallMeStmt() = default;
2519 
GetPUIdx()2520     PUIdx GetPUIdx() const
2521     {
2522         return puIdx;
2523     }
2524 
SetPUIdx(PUIdx idx)2525     void SetPUIdx(PUIdx idx)
2526     {
2527         puIdx = idx;
2528     }
2529 
GetTyIdx()2530     TyIdx GetTyIdx() const
2531     {
2532         return tyIdx;
2533     }
2534 
GetStmtID()2535     uint32 GetStmtID() const
2536     {
2537         return stmtID;
2538     }
2539 
2540     void Dump(const IRMap *) const;
GetMuList()2541     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
2542     {
2543         return &muList;
2544     }
2545 
GetChiList()2546     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2547     {
2548         return &chiList;
2549     }
2550 
GetMustDefList()2551     MapleVector<MustDefMeNode> *GetMustDefList()
2552     {
2553         return &mustDefList;
2554     }
2555 
GetMustDefList()2556     const MapleVector<MustDefMeNode> &GetMustDefList() const
2557     {
2558         return mustDefList;
2559     }
2560 
GetMustDefListItem(int i)2561     MustDefMeNode &GetMustDefListItem(int i)
2562     {
2563         return mustDefList[i];
2564     }
2565 
MustDefListSize()2566     size_t MustDefListSize() const
2567     {
2568         return mustDefList.size();
2569     }
2570 
GetAssignedLHS()2571     const ScalarMeExpr *GetAssignedLHS() const
2572     {
2573         return mustDefList.empty() ? nullptr : mustDefList.front().GetLHS();
2574     }
2575 
GetAssignedLHS()2576     ScalarMeExpr *GetAssignedLHS()
2577     {
2578         return mustDefList.empty() ? nullptr : mustDefList.front().GetLHS();
2579     }
2580 
GetLHSRef(bool excludeLocalRefVar)2581     MeExpr *GetLHSRef(bool excludeLocalRefVar)
2582     {
2583         return GetAssignedPartLHSRef(excludeLocalRefVar);
2584     }
2585 
GetVarLHS()2586     ScalarMeExpr *GetVarLHS()
2587     {
2588         if (mustDefList.empty() || mustDefList.front().GetLHS()->GetMeOp() != kMeOpVar) {
2589             return nullptr;
2590         }
2591         return static_cast<VarMeExpr *>(mustDefList.front().GetLHS());
2592     }
2593 
NeedDecref()2594     bool NeedDecref() const
2595     {
2596         return needDecref;
2597     }
2598 
EnableNeedDecref()2599     void EnableNeedDecref()
2600     {
2601         needDecref = true;
2602     }
2603 
DisableNeedDecref()2604     void DisableNeedDecref()
2605     {
2606         needDecref = false;
2607     }
2608 
NeedIncref()2609     bool NeedIncref() const
2610     {
2611         return needIncref;
2612     }
2613 
EnableNeedIncref()2614     void EnableNeedIncref()
2615     {
2616         needIncref = true;
2617     }
2618 
DisableNeedIncref()2619     void DisableNeedIncref()
2620     {
2621         needIncref = false;
2622     }
2623 
GetReturnType()2624     MIRType *GetReturnType() const
2625     {
2626         MIRFunction *callee = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
2627         return callee->GetReturnType();
2628     }
2629 
2630     const MIRFunction &GetTargetFunction() const;
2631     MIRFunction &GetTargetFunction();
2632     StmtNode &EmitStmt(SSATab &ssaTab);
2633 
2634     void SetCallReturn(ScalarMeExpr &);
2635 
2636 private:
2637     PUIdx puIdx = 0;
2638     // Used in trim call graph
2639     uint32 stmtID = 0;
2640     TyIdx tyIdx;
2641 };
2642 
2643 class IcallMeStmt : public NaryMeStmt, public MuChiMePart, public AssignedPart {
2644 public:
IcallMeStmt(MapleAllocator * alloc,const StmtNode * stt)2645     IcallMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2646         : NaryMeStmt(alloc, stt),
2647           MuChiMePart(alloc),
2648           AssignedPart(alloc),
2649           retTyIdx(static_cast<const IcallNode *>(stt)->GetRetTyIdx()),
2650           stmtID(stt->GetStmtID())
2651     {
2652     }
2653 
IcallMeStmt(MapleAllocator * alloc,Opcode op)2654     IcallMeStmt(MapleAllocator *alloc, Opcode op) : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc) {}
2655 
IcallMeStmt(MapleAllocator * alloc,const IcallMeStmt * cstmt)2656     IcallMeStmt(MapleAllocator *alloc, const IcallMeStmt *cstmt)
2657         : NaryMeStmt(alloc, cstmt),
2658           MuChiMePart(alloc),
2659           AssignedPart(alloc, this, cstmt->mustDefList),
2660           retTyIdx(cstmt->retTyIdx),
2661           stmtID(cstmt->stmtID)
2662     {
2663     }
2664 
IcallMeStmt(MapleAllocator * alloc,const NaryMeStmt * nary,TyIdx idx,uint32 id)2665     IcallMeStmt(MapleAllocator *alloc, const NaryMeStmt *nary, TyIdx idx, uint32 id)
2666         : NaryMeStmt(alloc, nary), MuChiMePart(alloc), AssignedPart(alloc), retTyIdx(idx), stmtID(id)
2667     {
2668     }
2669 
2670     virtual ~IcallMeStmt() = default;
2671 
2672     void Dump(const IRMap *) const;
GetMuList()2673     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
2674     {
2675         return &muList;
2676     }
2677 
GetChiList()2678     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2679     {
2680         return &chiList;
2681     }
2682 
GetMustDefList()2683     MapleVector<MustDefMeNode> *GetMustDefList()
2684     {
2685         return &mustDefList;
2686     }
2687 
GetMustDefList()2688     const MapleVector<MustDefMeNode> &GetMustDefList() const
2689     {
2690         return mustDefList;
2691     }
2692 
GetAssignedLHS()2693     const ScalarMeExpr *GetAssignedLHS() const
2694     {
2695         return mustDefList.empty() ? nullptr : mustDefList.front().GetLHS();
2696     }
2697 
GetAssignedLHS()2698     ScalarMeExpr *GetAssignedLHS()
2699     {
2700         return mustDefList.empty() ? nullptr : mustDefList.front().GetLHS();
2701     }
2702 
GetVarLHS()2703     ScalarMeExpr *GetVarLHS()
2704     {
2705         if (mustDefList.empty() || mustDefList.front().GetLHS()->GetMeOp() != kMeOpVar) {
2706             return nullptr;
2707         }
2708         return static_cast<VarMeExpr *>(mustDefList.front().GetLHS());
2709     }
2710 
GetLHSRef(bool excludeLocalRefVar)2711     MeExpr *GetLHSRef(bool excludeLocalRefVar)
2712     {
2713         return GetAssignedPartLHSRef(excludeLocalRefVar);
2714     }
2715 
NeedDecref()2716     bool NeedDecref() const
2717     {
2718         return needDecref;
2719     }
2720 
EnableNeedDecref()2721     void EnableNeedDecref()
2722     {
2723         needDecref = true;
2724     }
2725 
DisableNeedDecref()2726     void DisableNeedDecref()
2727     {
2728         needDecref = false;
2729     }
2730 
NeedIncref()2731     bool NeedIncref() const
2732     {
2733         return needIncref;
2734     }
2735 
EnableNeedIncref()2736     void EnableNeedIncref()
2737     {
2738         needIncref = true;
2739     }
2740 
DisableNeedIncref()2741     void DisableNeedIncref()
2742     {
2743         needIncref = false;
2744     }
2745 
GetReturnType()2746     MIRType *GetReturnType() const
2747     {
2748         return GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx);
2749     }
2750 
2751     StmtNode &EmitStmt(SSATab &ssaTab);
2752 
GetRetTyIdx()2753     TyIdx GetRetTyIdx() const
2754     {
2755         return retTyIdx;
2756     }
2757 
SetRetTyIdx(TyIdx idx)2758     void SetRetTyIdx(TyIdx idx)
2759     {
2760         retTyIdx = idx;
2761     }
2762 
GetStmtID()2763     uint32 GetStmtID() const
2764     {
2765         return stmtID;
2766     }
2767 
2768 private:
2769     // return type for callee
2770     TyIdx retTyIdx {0};
2771     // Used in trim call graph
2772     uint32 stmtID = 0;
2773 };
2774 
2775 class IntrinsiccallMeStmt : public NaryMeStmt, public MuChiMePart, public AssignedPart {
2776 public:
IntrinsiccallMeStmt(MapleAllocator * alloc,const StmtNode * stt)2777     IntrinsiccallMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2778         : NaryMeStmt(alloc, stt),
2779           MuChiMePart(alloc),
2780           AssignedPart(alloc),
2781           intrinsic(static_cast<const IntrinsiccallNode *>(stt)->GetIntrinsic()),
2782           tyIdx(static_cast<const IntrinsiccallNode *>(stt)->GetTyIdx()),
2783           retPType(stt->GetPrimType())
2784     {
2785     }
2786 
2787     IntrinsiccallMeStmt(MapleAllocator *alloc, Opcode op, MIRIntrinsicID id, TyIdx tyid = TyIdx())
NaryMeStmt(alloc,op)2788         : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc), intrinsic(id), tyIdx(tyid)
2789     {
2790     }
2791 
IntrinsiccallMeStmt(MapleAllocator * alloc,const IntrinsiccallMeStmt * intrn)2792     IntrinsiccallMeStmt(MapleAllocator *alloc, const IntrinsiccallMeStmt *intrn)
2793         : NaryMeStmt(alloc, intrn),
2794           MuChiMePart(alloc),
2795           AssignedPart(alloc, this, intrn->mustDefList),
2796           intrinsic(intrn->GetIntrinsic()),
2797           tyIdx(intrn->tyIdx),
2798           retPType(intrn->retPType)
2799     {
2800     }
2801 
IntrinsiccallMeStmt(MapleAllocator * alloc,const NaryMeStmt * nary,MIRIntrinsicID id,TyIdx idx,PrimType type)2802     IntrinsiccallMeStmt(MapleAllocator *alloc, const NaryMeStmt *nary, MIRIntrinsicID id, TyIdx idx, PrimType type)
2803         : NaryMeStmt(alloc, nary), MuChiMePart(alloc), AssignedPart(alloc), intrinsic(id), tyIdx(idx), retPType(type)
2804     {
2805     }
2806 
2807     virtual ~IntrinsiccallMeStmt() = default;
2808 
2809     void Dump(const IRMap *) const;
GetMuList()2810     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
2811     {
2812         return &muList;
2813     }
2814 
GetChiList()2815     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2816     {
2817         return &chiList;
2818     }
2819 
GetReturnType()2820     MIRType *GetReturnType() const
2821     {
2822         if (!mustDefList.empty()) {
2823             return GlobalTables::GetTypeTable().GetPrimType(mustDefList.front().GetLHS()->GetPrimType());
2824         }
2825         return GlobalTables::GetTypeTable().GetPrimType(retPType);
2826     }
2827 
GetMustDefList()2828     MapleVector<MustDefMeNode> *GetMustDefList()
2829     {
2830         return &mustDefList;
2831     }
2832 
GetMustDefList()2833     const MapleVector<MustDefMeNode> &GetMustDefList() const
2834     {
2835         return mustDefList;
2836     }
2837 
GetMustDefListItem(int i)2838     MustDefMeNode &GetMustDefListItem(int i)
2839     {
2840         return mustDefList[i];
2841     }
2842 
GetAssignedLHS()2843     const ScalarMeExpr *GetAssignedLHS() const
2844     {
2845         return mustDefList.empty() ? nullptr : mustDefList.front().GetLHS();
2846     }
2847 
GetAssignedLHS()2848     ScalarMeExpr *GetAssignedLHS()
2849     {
2850         return mustDefList.empty() ? nullptr : mustDefList.front().GetLHS();
2851     }
2852 
GetLHSRef(bool excludeLocalRefVar)2853     MeExpr *GetLHSRef(bool excludeLocalRefVar)
2854     {
2855         return GetAssignedPartLHSRef(excludeLocalRefVar);
2856     }
2857 
NeedDecref()2858     bool NeedDecref() const
2859     {
2860         return needDecref;
2861     }
2862 
EnableNeedDecref()2863     void EnableNeedDecref()
2864     {
2865         needDecref = true;
2866     }
2867 
DisableNeedDecref()2868     void DisableNeedDecref()
2869     {
2870         needDecref = false;
2871     }
2872 
NeedIncref()2873     bool NeedIncref() const
2874     {
2875         return needIncref;
2876     }
2877 
EnableNeedIncref()2878     void EnableNeedIncref()
2879     {
2880         needIncref = true;
2881     }
2882 
DisableNeedIncref()2883     void DisableNeedIncref()
2884     {
2885         needIncref = false;
2886     }
2887 
2888     StmtNode &EmitStmt(SSATab &ssaTab);
2889 
GetIntrinsic()2890     MIRIntrinsicID GetIntrinsic() const
2891     {
2892         return intrinsic;
2893     }
2894 
SetIntrinsic(MIRIntrinsicID id)2895     void SetIntrinsic(MIRIntrinsicID id)
2896     {
2897         intrinsic = id;
2898     }
2899 
GetTyIdx()2900     TyIdx GetTyIdx() const
2901     {
2902         return tyIdx;
2903     }
2904 
GetReturnPrimType()2905     PrimType GetReturnPrimType() const
2906     {
2907         return retPType;
2908     }
2909 
2910 private:
2911     MIRIntrinsicID intrinsic;
2912     TyIdx tyIdx;
2913     // Used to store return value type
2914     PrimType retPType = kPtyInvalid;
2915 };
2916 
2917 class AsmMeStmt : public NaryMeStmt, public MuChiMePart, public AssignedPart {
2918 public:
AsmMeStmt(MapleAllocator * alloc,const StmtNode * stt)2919     AsmMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2920         : NaryMeStmt(alloc, stt),
2921           MuChiMePart(alloc),
2922           AssignedPart(alloc),
2923           asmString(alloc->GetMemPool()),
2924           inputConstraints(alloc->Adapter()),
2925           outputConstraints(alloc->Adapter()),
2926           clobberList(alloc->Adapter()),
2927           gotoLabels(alloc->Adapter()),
2928           qualifiers(static_cast<const AsmNode *>(stt)->qualifiers)
2929     {
2930         asmString = static_cast<const AsmNode *>(stt)->asmString;
2931         inputConstraints = static_cast<const AsmNode *>(stt)->inputConstraints;
2932         outputConstraints = static_cast<const AsmNode *>(stt)->outputConstraints;
2933         clobberList = static_cast<const AsmNode *>(stt)->clobberList;
2934         gotoLabels = static_cast<const AsmNode *>(stt)->gotoLabels;
2935     }
2936 
AsmMeStmt(MapleAllocator * alloc,const AsmMeStmt * stt)2937     AsmMeStmt(MapleAllocator *alloc, const AsmMeStmt *stt)
2938         : NaryMeStmt(alloc, stt),
2939           MuChiMePart(alloc),
2940           AssignedPart(alloc),
2941           asmString(alloc->GetMemPool()),
2942           inputConstraints(alloc->Adapter()),
2943           outputConstraints(alloc->Adapter()),
2944           clobberList(alloc->Adapter()),
2945           gotoLabels(alloc->Adapter()),
2946           qualifiers(stt->qualifiers)
2947     {
2948         asmString = stt->asmString;
2949         inputConstraints = stt->inputConstraints;
2950         outputConstraints = stt->outputConstraints;
2951         clobberList = stt->clobberList;
2952         gotoLabels = stt->gotoLabels;
2953     }
2954 
2955     virtual ~AsmMeStmt() = default;
2956     void Dump(const IRMap *) const;
GetMuList()2957     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
2958     {
2959         return &muList;
2960     }
GetChiList()2961     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
2962     {
2963         return &chiList;
2964     }
GetMustDefList()2965     MapleVector<MustDefMeNode> *GetMustDefList()
2966     {
2967         return &mustDefList;
2968     }
2969     StmtNode &EmitStmt(SSATab &ssaTab);
2970 
2971     MapleString asmString;
2972     MapleVector<UStrIdx> inputConstraints;   // length is numOpnds
2973     MapleVector<UStrIdx> outputConstraints;  // length is returnValues.size()
2974     MapleVector<UStrIdx> clobberList;
2975     MapleVector<LabelIdx> gotoLabels;
2976     uint32 qualifiers;
2977 };
2978 
2979 class RetMeStmt : public NaryMeStmt {
2980 public:
RetMeStmt(MapleAllocator * alloc,const StmtNode * stt)2981     RetMeStmt(MapleAllocator *alloc, const StmtNode *stt)
2982         : NaryMeStmt(alloc, stt), muList(std::less<OStIdx>(), alloc->Adapter())
2983     {
2984     }
2985 
2986     ~RetMeStmt() = default;
2987 
2988     void Dump(const IRMap *) const;
GetMuList()2989     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
2990     {
2991         return &muList;
2992     }
2993 
2994 private:
2995     MapleMap<OStIdx, ScalarMeExpr *> muList;
2996 };
2997 
2998 // eval, free, decref, incref, decrefreset, assertnonnull, igoto
2999 class UnaryMeStmt : public MeStmt {
3000 public:
UnaryMeStmt(const StmtNode * stt)3001     explicit UnaryMeStmt(const StmtNode *stt) : MeStmt(stt) {}
3002 
UnaryMeStmt(Opcode o)3003     explicit UnaryMeStmt(Opcode o) : MeStmt(o) {}
3004 
UnaryMeStmt(const UnaryMeStmt * umestmt)3005     explicit UnaryMeStmt(const UnaryMeStmt *umestmt) : MeStmt(umestmt->GetOp()), opnd(umestmt->opnd) {}
3006 
3007     virtual ~UnaryMeStmt() = default;
3008 
NumMeStmtOpnds()3009     size_t NumMeStmtOpnds() const
3010     {
3011         return kOperandNumUnary;
3012     }
3013 
GetOpnd(size_t)3014     MeExpr *GetOpnd(size_t) const
3015     {
3016         return opnd;
3017     }
3018 
SetOpnd(size_t,MeExpr * val)3019     void SetOpnd(size_t, MeExpr *val)
3020     {
3021         opnd = val;
3022     }
3023 
GetOpnd()3024     MeExpr *GetOpnd() const
3025     {
3026         return opnd;
3027     }
3028 
SetMeStmtOpndValue(MeExpr * val)3029     void SetMeStmtOpndValue(MeExpr *val)
3030     {
3031         opnd = val;
3032     }
3033 
3034     void Dump(const IRMap *) const;
3035 
3036     StmtNode &EmitStmt(SSATab &ssaTab);
3037 
3038 private:
3039     MeExpr *opnd = nullptr;
3040 };
3041 
3042 class SafetyCallCheckMeStmt {
3043 public:
SafetyCallCheckMeStmt(GStrIdx funcNameIdx,size_t paramIndex,GStrIdx stmtFuncNameIdx)3044     SafetyCallCheckMeStmt(GStrIdx funcNameIdx, size_t paramIndex, GStrIdx stmtFuncNameIdx)
3045         : funcNameIdx(funcNameIdx), paramIndex(paramIndex), stmtFuncNameIdx(stmtFuncNameIdx)
3046     {
3047     }
SafetyCallCheckMeStmt(const SafetyCallCheckMeStmt & stmt)3048     explicit SafetyCallCheckMeStmt(const SafetyCallCheckMeStmt &stmt)
3049         : funcNameIdx(stmt.GetFuncNameIdx()),
3050           paramIndex(stmt.GetParamIndex()),
3051           stmtFuncNameIdx(stmt.GetStmtFuncNameIdx())
3052     {
3053     }
3054 
3055     virtual ~SafetyCallCheckMeStmt() = default;
3056 
GetFuncName()3057     const std::string &GetFuncName() const
3058     {
3059         return GlobalTables::GetStrTable().GetStringFromStrIdx(funcNameIdx);
3060     }
3061 
GetStmtFuncName()3062     const std::string &GetStmtFuncName() const
3063     {
3064         return GlobalTables::GetStrTable().GetStringFromStrIdx(stmtFuncNameIdx);
3065     }
3066 
GetFuncNameIdx()3067     GStrIdx GetFuncNameIdx() const
3068     {
3069         return funcNameIdx;
3070     }
3071 
GetParamIndex()3072     size_t GetParamIndex() const
3073     {
3074         return paramIndex;
3075     }
3076 
GetStmtFuncNameIdx()3077     GStrIdx GetStmtFuncNameIdx() const
3078     {
3079         return stmtFuncNameIdx;
3080     }
3081 
3082 private:
3083     GStrIdx funcNameIdx;
3084     size_t paramIndex;
3085     GStrIdx stmtFuncNameIdx;
3086 };
3087 
3088 class SafetyCheckMeStmt {
3089 public:
SafetyCheckMeStmt(GStrIdx funcNameIdx)3090     explicit SafetyCheckMeStmt(GStrIdx funcNameIdx) : funcNameIdx(funcNameIdx) {}
SafetyCheckMeStmt(const SafetyCheckMeStmt & stmt)3091     explicit SafetyCheckMeStmt(const SafetyCheckMeStmt &stmt) : funcNameIdx(stmt.GetFuncNameIdx()) {}
SafetyCheckMeStmt()3092     SafetyCheckMeStmt() {}
3093 
3094     virtual ~SafetyCheckMeStmt() = default;
3095 
GetFuncName()3096     const std::string &GetFuncName() const
3097     {
3098         return GlobalTables::GetStrTable().GetStringFromStrIdx(funcNameIdx);
3099     }
3100 
GetFuncNameIdx()3101     GStrIdx GetFuncNameIdx() const
3102     {
3103         return funcNameIdx;
3104     }
3105 
3106 private:
3107     GStrIdx funcNameIdx;
3108 };
3109 
3110 class AssertNonnullMeStmt : public UnaryMeStmt, public SafetyCheckMeStmt {
3111 public:
AssertNonnullMeStmt(const AssertNonnullStmtNode * stt)3112     explicit AssertNonnullMeStmt(const AssertNonnullStmtNode *stt)
3113         : UnaryMeStmt(stt), SafetyCheckMeStmt(stt->GetFuncNameIdx())
3114     {
3115     }
AssertNonnullMeStmt(const UnaryStmtNode * stt)3116     explicit AssertNonnullMeStmt(const UnaryStmtNode *stt) : UnaryMeStmt(stt), SafetyCheckMeStmt() {}
AssertNonnullMeStmt(const AssertNonnullMeStmt & stt)3117     explicit AssertNonnullMeStmt(const AssertNonnullMeStmt &stt)
3118         : UnaryMeStmt(&stt), SafetyCheckMeStmt(static_cast<const SafetyCheckMeStmt &>(stt))
3119     {
3120     }
3121     ~AssertNonnullMeStmt() = default;
3122     StmtNode &EmitStmt(SSATab &ssaTab);
3123 };
3124 
3125 class CallAssertNonnullMeStmt : public UnaryMeStmt, public SafetyCallCheckMeStmt {
3126 public:
CallAssertNonnullMeStmt(const CallAssertNonnullStmtNode * stt)3127     explicit CallAssertNonnullMeStmt(const CallAssertNonnullStmtNode *stt)
3128         : UnaryMeStmt(stt),
3129           SafetyCallCheckMeStmt(stt->GetFuncNameIdx(), stt->GetParamIndex(), stt->GetStmtFuncNameIdx())
3130     {
3131     }
CallAssertNonnullMeStmt(Opcode o,GStrIdx funcNameIdx,size_t paramIndex,GStrIdx stmtFuncNameIdx)3132     CallAssertNonnullMeStmt(Opcode o, GStrIdx funcNameIdx, size_t paramIndex, GStrIdx stmtFuncNameIdx)
3133         : UnaryMeStmt(o), SafetyCallCheckMeStmt(funcNameIdx, paramIndex, stmtFuncNameIdx)
3134     {
3135     }
CallAssertNonnullMeStmt(const CallAssertNonnullMeStmt & stt)3136     explicit CallAssertNonnullMeStmt(const CallAssertNonnullMeStmt &stt)
3137         : UnaryMeStmt(stt), SafetyCallCheckMeStmt(static_cast<const SafetyCallCheckMeStmt &>(stt))
3138     {
3139     }
CallAssertNonnullMeStmt(const CallAssertNonnullMeStmt * stt)3140     explicit CallAssertNonnullMeStmt(const CallAssertNonnullMeStmt *stt)
3141         : UnaryMeStmt(*stt), SafetyCallCheckMeStmt(static_cast<const SafetyCallCheckMeStmt &>(*stt))
3142     {
3143     }
3144     ~CallAssertNonnullMeStmt() = default;
3145     StmtNode &EmitStmt(SSATab &ssaTab);
3146 };
3147 
3148 class AssertBoundaryMeStmt : public NaryMeStmt, public SafetyCheckMeStmt {
3149 public:
AssertBoundaryMeStmt(MapleAllocator * alloc,const AssertBoundaryStmtNode * stt)3150     AssertBoundaryMeStmt(MapleAllocator *alloc, const AssertBoundaryStmtNode *stt)
3151         : NaryMeStmt(alloc, stt), SafetyCheckMeStmt(stt->GetFuncNameIdx())
3152     {
3153     }
AssertBoundaryMeStmt(MapleAllocator * alloc,const AssertBoundaryMeStmt & stt)3154     AssertBoundaryMeStmt(MapleAllocator *alloc, const AssertBoundaryMeStmt &stt)
3155         : NaryMeStmt(alloc, static_cast<const NaryMeStmt *>(&stt)),
3156           SafetyCheckMeStmt(static_cast<const SafetyCheckMeStmt &>(stt))
3157     {
3158     }
3159     ~AssertBoundaryMeStmt() = default;
3160     StmtNode &EmitStmt(SSATab &ssaTab);
3161 };
3162 
3163 class CallAssertBoundaryMeStmt : public NaryMeStmt, public SafetyCallCheckMeStmt {
3164 public:
CallAssertBoundaryMeStmt(MapleAllocator * alloc,const CallAssertBoundaryStmtNode * stt)3165     CallAssertBoundaryMeStmt(MapleAllocator *alloc, const CallAssertBoundaryStmtNode *stt)
3166         : NaryMeStmt(alloc, stt),
3167           SafetyCallCheckMeStmt(stt->GetFuncNameIdx(), stt->GetParamIndex(), stt->GetStmtFuncNameIdx())
3168     {
3169     }
CallAssertBoundaryMeStmt(MapleAllocator * alloc,const CallAssertBoundaryMeStmt & stt)3170     CallAssertBoundaryMeStmt(MapleAllocator *alloc, const CallAssertBoundaryMeStmt &stt)
3171         : NaryMeStmt(alloc, static_cast<const NaryMeStmt *>(&stt)),
3172           SafetyCallCheckMeStmt(static_cast<const SafetyCallCheckMeStmt &>(stt))
3173     {
3174     }
3175     ~CallAssertBoundaryMeStmt() = default;
3176     StmtNode &EmitStmt(SSATab &ssaTab);
3177 };
3178 
3179 class GotoMeStmt : public MeStmt {
3180 public:
GotoMeStmt(const StmtNode * stt)3181     explicit GotoMeStmt(const StmtNode *stt) : MeStmt(stt), offset(static_cast<const GotoNode *>(stt)->GetOffset()) {}
GotoMeStmt(const GotoMeStmt & condGoto)3182     explicit GotoMeStmt(const GotoMeStmt &condGoto) : MeStmt(MeStmt(condGoto.GetOp())), offset(condGoto.GetOffset()) {}
GotoMeStmt(uint32 o)3183     explicit GotoMeStmt(uint32 o) : MeStmt(OP_goto), offset(o) {}
3184 
3185     ~GotoMeStmt() = default;
3186 
GetOffset()3187     uint32 GetOffset() const
3188     {
3189         return offset;
3190     }
3191 
SetOffset(uint32 o)3192     void SetOffset(uint32 o)
3193     {
3194         offset = o;
3195     }
3196 
3197     StmtNode &EmitStmt(SSATab &ssaTab);
3198 
3199 private:
3200     uint32 offset;  // the label
3201 };
3202 
3203 class CondGotoMeStmt : public UnaryMeStmt {
3204 public:
CondGotoMeStmt(const StmtNode * stt)3205     explicit CondGotoMeStmt(const StmtNode *stt)
3206         : UnaryMeStmt(stt),
3207           offset(static_cast<const CondGotoNode *>(stt)->GetOffset()),
3208           branchProb(static_cast<const CondGotoNode *>(stt)->GetBranchProb())
3209     {
3210     }
3211 
CondGotoMeStmt(const CondGotoMeStmt & condGoto)3212     explicit CondGotoMeStmt(const CondGotoMeStmt &condGoto)
3213         : UnaryMeStmt(static_cast<const UnaryMeStmt *>(&condGoto)),
3214           offset(condGoto.GetOffset()),
3215           branchProb(condGoto.branchProb)
3216     {
3217     }
3218 
CondGotoMeStmt(const UnaryMeStmt & unaryMeStmt,uint32 o)3219     CondGotoMeStmt(const UnaryMeStmt &unaryMeStmt, uint32 o) : UnaryMeStmt(&unaryMeStmt), offset(o) {}
3220 
3221     ~CondGotoMeStmt() = default;
3222 
GetOffset()3223     uint32 GetOffset() const
3224     {
3225         return offset;
3226     }
3227 
SetOffset(uint32 currOffset)3228     void SetOffset(uint32 currOffset)
3229     {
3230         offset = currOffset;
3231     }
3232 
IsBranchProbValid()3233     bool IsBranchProbValid() const
3234     {
3235         return branchProb > 0 && branchProb < CondGotoNode::probAll;
3236     }
3237 
GetBranchProb()3238     int32 GetBranchProb() const
3239     {
3240         return branchProb;
3241     }
3242 
SetBranchProb(int32 prob)3243     void SetBranchProb(int32 prob)
3244     {
3245         branchProb = prob;
3246     }
3247 
ReverseBranchProb()3248     void ReverseBranchProb()
3249     {
3250         if (IsBranchProbValid()) {
3251             branchProb = CondGotoNode::probAll - branchProb;
3252         }
3253     }
3254 
InvalidateBranchProb()3255     void InvalidateBranchProb()
3256     {
3257         if (IsBranchProbValid()) {
3258             branchProb = -1;
3259         }
3260     }
3261 
3262     void Dump(const IRMap *) const;
3263     StmtNode &EmitStmt(SSATab &ssaTab);
3264 
3265 private:
3266     uint32 offset;          // the label
3267     int32 branchProb = -1;  // branch probability, a negative number indicates that the probability is invalid
3268 };
3269 
3270 class JsTryMeStmt : public MeStmt {
3271 public:
JsTryMeStmt(const StmtNode * stt)3272     explicit JsTryMeStmt(const StmtNode *stt)
3273         : MeStmt(stt),
3274           catchOffset(static_cast<const JsTryNode *>(stt)->GetCatchOffset()),
3275           finallyOffset(static_cast<const JsTryNode *>(stt)->GetFinallyOffset())
3276     {
3277     }
3278 
3279     ~JsTryMeStmt() = default;
3280 
3281     StmtNode &EmitStmt(SSATab &ssaTab);
3282 
3283 private:
3284     uint16 catchOffset;
3285     uint16 finallyOffset;
3286 };
3287 
3288 class TryMeStmt : public MeStmt {
3289 public:
TryMeStmt(MapleAllocator * alloc,const StmtNode * stt)3290     TryMeStmt(MapleAllocator *alloc, const StmtNode *stt) : MeStmt(stt), offsets(alloc->Adapter()) {}
3291 
3292     ~TryMeStmt() = default;
3293 
OffsetsPushBack(LabelIdx curr)3294     void OffsetsPushBack(LabelIdx curr)
3295     {
3296         offsets.push_back(curr);
3297     }
3298 
GetOffsets()3299     const MapleVector<LabelIdx> &GetOffsets() const
3300     {
3301         return offsets;
3302     }
3303 
3304     StmtNode &EmitStmt(SSATab &ssaTab);
3305 
3306 private:
3307     MapleVector<LabelIdx> offsets;
3308 };
3309 
3310 class CatchMeStmt : public MeStmt {
3311 public:
CatchMeStmt(MapleAllocator * alloc,const StmtNode * stt)3312     CatchMeStmt(MapleAllocator *alloc, const StmtNode *stt) : MeStmt(stt), exceptionTyIdxVec(alloc->Adapter())
3313     {
3314         for (auto it : static_cast<const CatchNode *>(stt)->GetExceptionTyIdxVec()) {
3315             exceptionTyIdxVec.push_back(it);
3316         }
3317     }
3318 
3319     ~CatchMeStmt() = default;
3320 
3321     StmtNode &EmitStmt(SSATab &ssaTab);
GetExceptionTyIdxVec()3322     const MapleVector<TyIdx> &GetExceptionTyIdxVec() const
3323     {
3324         return exceptionTyIdxVec;
3325     }
3326 
3327 private:
3328     MapleVector<TyIdx> exceptionTyIdxVec;
3329 };
3330 
3331 class CppCatchMeStmt : public MeStmt {
3332 public:
3333     TyIdx exceptionTyIdx;
3334 
CppCatchMeStmt(const MapleAllocator * alloc,const StmtNode * stt)3335     CppCatchMeStmt(const MapleAllocator *alloc, const StmtNode *stt) : MeStmt(stt)
3336     {
3337         (void)alloc;
3338     }
3339 
3340     ~CppCatchMeStmt() = default;
3341     StmtNode &EmitStmt(SSATab &ssaTab);
3342 };
3343 
3344 class SwitchMeStmt : public UnaryMeStmt {
3345 public:
SwitchMeStmt(MapleAllocator * alloc,StmtNode * stt)3346     SwitchMeStmt(MapleAllocator *alloc, StmtNode *stt)
3347         : UnaryMeStmt(stt),
3348           defaultLabel(static_cast<SwitchNode *>(stt)->GetDefaultLabel()),
3349           switchTable(alloc->Adapter())
3350     {
3351         switchTable = static_cast<SwitchNode *>(stt)->GetSwitchTable();
3352     }
3353 
3354     ~SwitchMeStmt() = default;
3355 
GetDefaultLabel()3356     LabelIdx GetDefaultLabel() const
3357     {
3358         return defaultLabel;
3359     }
3360 
SetDefaultLabel(LabelIdx curr)3361     void SetDefaultLabel(LabelIdx curr)
3362     {
3363         defaultLabel = curr;
3364     }
3365 
SetCaseLabel(size_t caseIdx,LabelIdx label)3366     void SetCaseLabel(size_t caseIdx, LabelIdx label)
3367     {
3368         switchTable[caseIdx].second = label;
3369     }
3370 
GetSwitchTable()3371     CaseVector &GetSwitchTable()
3372     {
3373         return switchTable;
3374     }
3375 
3376     void Dump(const IRMap *) const;
3377     StmtNode &EmitStmt(SSATab &ssatab);
3378 
3379 private:
3380     LabelIdx defaultLabel;
3381     CaseVector switchTable;
3382 };
3383 
3384 class CommentMeStmt : public MeStmt {
3385 public:
CommentMeStmt(const MapleAllocator * alloc,const StmtNode * stt)3386     CommentMeStmt(const MapleAllocator *alloc, const StmtNode *stt) : MeStmt(stt), comment(alloc->GetMemPool())
3387     {
3388         comment = static_cast<const CommentNode *>(stt)->GetComment();
3389     }
3390 
3391     ~CommentMeStmt() = default;
3392 
3393     StmtNode &EmitStmt(SSATab &ssaTab);
GetComment()3394     const MapleString &GetComment()
3395     {
3396         return comment;
3397     }
GetComment()3398     const MapleString &GetComment() const
3399     {
3400         return comment;
3401     }
3402 
3403 private:
3404     MapleString comment;
3405 };
3406 
3407 class WithMuMeStmt : public MeStmt {
3408 public:
WithMuMeStmt(MapleAllocator * alloc,const StmtNode * stt)3409     WithMuMeStmt(MapleAllocator *alloc, const StmtNode *stt)
3410         : MeStmt(stt), muList(std::less<OStIdx>(), alloc->Adapter())
3411     {
3412     }
3413 
3414     virtual ~WithMuMeStmt() = default;
3415 
GetMuList()3416     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
3417     {
3418         return &muList;
3419     }
3420 
GetMuList()3421     const MapleMap<OStIdx, ScalarMeExpr *> *GetMuList() const
3422     {
3423         return &muList;
3424     }
3425 
3426 private:
3427     MapleMap<OStIdx, ScalarMeExpr *> muList;
3428 };
3429 
3430 class GosubMeStmt : public WithMuMeStmt {
3431 public:
GosubMeStmt(MapleAllocator * alloc,const StmtNode * stt)3432     GosubMeStmt(MapleAllocator *alloc, const StmtNode *stt)
3433         : WithMuMeStmt(alloc, stt), offset(static_cast<const GotoNode *>(stt)->GetOffset())
3434     {
3435     }
3436 
3437     ~GosubMeStmt() = default;
3438 
3439     void Dump(const IRMap *) const;
3440     StmtNode &EmitStmt(SSATab &ssatab);
3441 
3442 private:
3443     uint32 offset;  // the label
3444 };
3445 
3446 class ThrowMeStmt : public WithMuMeStmt {
3447 public:
ThrowMeStmt(MapleAllocator * alloc,const StmtNode * stt)3448     ThrowMeStmt(MapleAllocator *alloc, const StmtNode *stt) : WithMuMeStmt(alloc, stt) {}
3449 
3450     ~ThrowMeStmt() = default;
3451 
NumMeStmtOpnds()3452     size_t NumMeStmtOpnds() const
3453     {
3454         return kOperandNumUnary;
3455     }
3456 
GetOpnd(size_t)3457     MeExpr *GetOpnd(size_t) const
3458     {
3459         return opnd;
3460     }
3461 
SetOpnd(size_t,MeExpr * val)3462     void SetOpnd(size_t, MeExpr *val)
3463     {
3464         opnd = val;
3465     }
3466 
GetOpnd()3467     MeExpr *GetOpnd() const
3468     {
3469         return opnd;
3470     }
3471 
SetMeStmtOpndValue(MeExpr * val)3472     void SetMeStmtOpndValue(MeExpr *val)
3473     {
3474         opnd = val;
3475     }
3476 
3477     void Dump(const IRMap *) const;
3478     StmtNode &EmitStmt(SSATab &ssaTab);
3479 
3480 private:
3481     MeExpr *opnd = nullptr;
3482 };
3483 
3484 class SyncMeStmt : public NaryMeStmt, public MuChiMePart {
3485 public:
SyncMeStmt(MapleAllocator * alloc,const StmtNode * stt)3486     SyncMeStmt(MapleAllocator *alloc, const StmtNode *stt) : NaryMeStmt(alloc, stt), MuChiMePart(alloc) {}
3487 
3488     ~SyncMeStmt() = default;
3489 
3490     void Dump(const IRMap *) const;
GetMuList()3491     MapleMap<OStIdx, ScalarMeExpr *> *GetMuList()
3492     {
3493         return &muList;
3494     }
3495 
GetChiList()3496     MapleMap<OStIdx, ChiMeNode *> *GetChiList()
3497     {
3498         return &chiList;
3499     }
3500 };
3501 
3502 MapleMap<OStIdx, ChiMeNode *> *GenericGetChiListFromVarMeExpr(ScalarMeExpr &expr);
3503 void DumpMuList(const IRMap *irMap, const MapleMap<OStIdx, ScalarMeExpr *> &muList);
3504 void DumpChiList(const IRMap *irMap, const MapleMap<OStIdx, ChiMeNode *> &chiList);
3505 class DumpOptions {
3506 public:
GetSimpleDump()3507     static bool GetSimpleDump()
3508     {
3509         return simpleDump;
3510     }
3511 
GetDumpVsyNum()3512     static int GetDumpVsyNum()
3513     {
3514         return dumpVsymNum;
3515     }
3516 
3517 private:
3518     static bool simpleDump;
3519     static int dumpVsymNum;
3520 };
3521 }  // namespace maple
3522 #define LOAD_SAFE_CAST_FOR_ME_EXPR
3523 #define LOAD_SAFE_CAST_FOR_ME_STMT
3524 #include "me_safe_cast_traits.def"
3525 #endif  // MAPLE_ME_INCLUDE_ME_IR_H
3526