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