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