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