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