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_CONST_H 17 #define MAPLE_IR_INCLUDE_MIR_CONST_H 18 #include <math.h> 19 #include "mir_type.h" 20 #include "mpl_int_val.h" 21 22 namespace maple { 23 class MIRConst; // circular dependency exists, no other choice 24 using MIRConstPtr = MIRConst *; 25 #if MIR_FEATURE_FULL 26 class MIRSymbol; // circular dependency exists, no other choice 27 enum MIRConstKind { 28 kConstInvalid, 29 kConstInt, 30 kConstAddrof, 31 kConstAddrofFunc, 32 kConstLblConst, 33 kConstStrConst, 34 kConstStr16Const, 35 kConstFloatConst, 36 kConstDoubleConst, 37 kConstFloat128Const, 38 kConstAggConst, 39 kConstStConst 40 }; 41 42 class MIRConst { 43 public: 44 explicit MIRConst(MIRType &type, MIRConstKind constKind = kConstInvalid) : type(&type), kind(constKind) {} 45 46 virtual ~MIRConst() = default; 47 48 virtual void Dump(const MIRSymbolTable *localSymTab = nullptr) const 49 { 50 (void)localSymTab; 51 } 52 GetFieldId()53 uint32 GetFieldId() const 54 { 55 return fieldID; 56 } 57 SetFieldId(uint32 fieldIdx)58 void SetFieldId(uint32 fieldIdx) 59 { 60 DoSetFieldId(fieldIdx); 61 } 62 IsZero()63 virtual bool IsZero() const 64 { 65 return false; 66 } 67 IsOne()68 virtual bool IsOne() const 69 { 70 return false; 71 } 72 IsMagicNum()73 virtual bool IsMagicNum() const 74 { 75 return false; 76 } 77 78 // NO OP Neg()79 virtual void Neg() {} 80 81 virtual bool operator==(const MIRConst &rhs) const 82 { 83 return &rhs == this; 84 } 85 86 virtual MIRConst *Clone(MemPool &memPool) const = 0; 87 GetKind()88 MIRConstKind GetKind() const 89 { 90 return kind; 91 } 92 GetType()93 MIRType &GetType() 94 { 95 return *type; 96 } 97 GetType()98 const MIRType &GetType() const 99 { 100 return *type; 101 } 102 SetType(MIRType & t)103 void SetType(MIRType &t) 104 { 105 type = &t; 106 } 107 108 protected: 109 uint32 fieldID = 0; 110 111 private: 112 MIRType *type; 113 MIRConstKind kind; DoSetFieldId(uint32 fieldIdx)114 virtual void DoSetFieldId(uint32 fieldIdx) 115 { 116 DEBUG_ASSERT(kind != kConstInt, "must be"); 117 fieldID = fieldIdx; 118 } 119 }; 120 121 class MIRIntConst : public MIRConst { 122 public: MIRIntConst(uint64 val,MIRType & type)123 MIRIntConst(uint64 val, MIRType &type) : MIRConst(type, kConstInt), value(val, type.GetPrimType()) {} 124 MIRIntConst(const IntVal & val,MIRType & type)125 MIRIntConst(const IntVal &val, MIRType &type) : MIRConst(type, kConstInt), value(val) 126 { 127 [[maybe_unused]] PrimType pType = type.GetPrimType(); 128 DEBUG_ASSERT( 129 IsPrimitiveInteger(pType) && GetPrimTypeActualBitSize(pType) <= value.GetBitWidth(), 130 "Constant is tried to be constructed with non-integral type or bit-width is not appropriate for it"); 131 } 132 133 /// @return number of used bits in the value 134 uint8 GetActualBitWidth() const; 135 Trunc(uint8 width)136 void Trunc(uint8 width) 137 { 138 value.TruncInPlace(width); 139 } 140 141 void Dump(const MIRSymbolTable *localSymTab) const override; 142 IsNegative()143 bool IsNegative() const 144 { 145 return value.IsSigned() && value.GetSignBit(); 146 } 147 IsPositive()148 bool IsPositive() const 149 { 150 return !IsNegative() && value != 0; 151 } 152 IsZero()153 bool IsZero() const override 154 { 155 return value == 0; 156 } 157 IsOne()158 bool IsOne() const override 159 { 160 return value == 1; 161 } 162 Neg()163 void Neg() override 164 { 165 value = -value; 166 } 167 GetValue()168 const IntVal &GetValue() const 169 { 170 return value; 171 } 172 173 int64 GetExtValue(uint8 size = 0) const 174 { 175 return value.GetExtValue(size); 176 } 177 178 int64 GetSXTValue(uint8 size = 0) const 179 { 180 return value.GetSXTValue(size); 181 } 182 183 uint64 GetZXTValue(uint8 size = 0) const 184 { 185 return value.GetZXTValue(size); 186 } 187 SetValue(int64 val)188 void SetValue(int64 val) const 189 { 190 (void)val; 191 CHECK_FATAL(false, "Can't Use This Interface in This Object"); 192 } 193 194 bool operator==(const MIRConst &rhs) const override; 195 Clone(MemPool & memPool)196 MIRIntConst *Clone(MemPool &memPool) const override 197 { 198 CHECK_FATAL(false, "Can't Use This Interface in This Object"); 199 } 200 201 private: 202 IntVal value; 203 DoSetFieldId(uint32 fieldIdx)204 void DoSetFieldId(uint32 fieldIdx) override 205 { 206 DEBUG_ASSERT(false, "Can't Use This Interface in This Object"); 207 (void)fieldIdx; 208 } 209 }; 210 211 class MIRAddrofConst : public MIRConst { 212 public: MIRAddrofConst(StIdx sy,FieldID fi,MIRType & ty)213 MIRAddrofConst(StIdx sy, FieldID fi, MIRType &ty) : MIRConst(ty, kConstAddrof), stIdx(sy), fldID(fi), offset(0) {} 214 MIRAddrofConst(StIdx sy,FieldID fi,MIRType & ty,int32 ofst)215 MIRAddrofConst(StIdx sy, FieldID fi, MIRType &ty, int32 ofst) 216 : MIRConst(ty, kConstAddrof), stIdx(sy), fldID(fi), offset(ofst) 217 { 218 } 219 220 ~MIRAddrofConst() = default; 221 GetSymbolIndex()222 StIdx GetSymbolIndex() const 223 { 224 return stIdx; 225 } 226 SetSymbolIndex(StIdx idx)227 void SetSymbolIndex(StIdx idx) 228 { 229 stIdx = idx; 230 } 231 GetFieldID()232 FieldID GetFieldID() const 233 { 234 return fldID; 235 } 236 GetOffset()237 int32 GetOffset() const 238 { 239 return offset; 240 } 241 242 void Dump(const MIRSymbolTable *localSymTab) const override; 243 244 bool operator==(const MIRConst &rhs) const override; 245 Clone(MemPool & memPool)246 MIRAddrofConst *Clone(MemPool &memPool) const override 247 { 248 return memPool.New<MIRAddrofConst>(*this); 249 } 250 251 private: 252 StIdx stIdx; 253 FieldID fldID; 254 int32 offset; 255 }; 256 257 class MIRAddroffuncConst : public MIRConst { 258 public: MIRAddroffuncConst(PUIdx idx,MIRType & ty)259 MIRAddroffuncConst(PUIdx idx, MIRType &ty) : MIRConst(ty, kConstAddrofFunc), puIdx(idx) {} 260 261 ~MIRAddroffuncConst() = default; 262 GetValue()263 PUIdx GetValue() const 264 { 265 return puIdx; 266 } 267 268 void Dump(const MIRSymbolTable *localSymTab) const override; 269 270 bool operator==(const MIRConst &rhs) const override; 271 Clone(MemPool & memPool)272 MIRAddroffuncConst *Clone(MemPool &memPool) const override 273 { 274 return memPool.New<MIRAddroffuncConst>(*this); 275 } 276 277 private: 278 PUIdx puIdx; 279 }; 280 281 class MIRLblConst : public MIRConst { 282 public: MIRLblConst(LabelIdx val,PUIdx pidx,MIRType & type)283 MIRLblConst(LabelIdx val, PUIdx pidx, MIRType &type) : MIRConst(type, kConstLblConst), value(val), puIdx(pidx) {} 284 285 ~MIRLblConst() = default; 286 287 void Dump(const MIRSymbolTable *localSymTab) const override; 288 bool operator==(const MIRConst &rhs) const override; 289 Clone(MemPool & memPool)290 MIRLblConst *Clone(MemPool &memPool) const override 291 { 292 return memPool.New<MIRLblConst>(*this); 293 } 294 GetValue()295 LabelIdx GetValue() const 296 { 297 return value; 298 } 299 GetPUIdx()300 PUIdx GetPUIdx() const 301 { 302 return puIdx; 303 } 304 305 private: 306 LabelIdx value; 307 PUIdx puIdx; 308 }; 309 310 class MIRStrConst : public MIRConst { 311 public: MIRStrConst(UStrIdx val,MIRType & type)312 MIRStrConst(UStrIdx val, MIRType &type) : MIRConst(type, kConstStrConst), value(val) {} 313 314 MIRStrConst(const std::string &str, MIRType &type); 315 316 ~MIRStrConst() = default; 317 318 void Dump(const MIRSymbolTable *localSymTab) const override; 319 bool operator==(const MIRConst &rhs) const override; 320 Clone(MemPool & memPool)321 MIRStrConst *Clone(MemPool &memPool) const override 322 { 323 return memPool.New<MIRStrConst>(*this); 324 } 325 GetValue()326 UStrIdx GetValue() const 327 { 328 return value; 329 } 330 GetPrimType()331 static PrimType GetPrimType() 332 { 333 return kPrimType; 334 } 335 336 private: 337 UStrIdx value; 338 static const PrimType kPrimType = PTY_ptr; 339 }; 340 341 class MIRStr16Const : public MIRConst { 342 public: MIRStr16Const(const U16StrIdx & val,MIRType & type)343 MIRStr16Const(const U16StrIdx &val, MIRType &type) : MIRConst(type, kConstStr16Const), value(val) {} 344 345 MIRStr16Const(const std::u16string &str, MIRType &type); 346 ~MIRStr16Const() = default; 347 GetPrimType()348 static PrimType GetPrimType() 349 { 350 return kPrimType; 351 } 352 353 void Dump(const MIRSymbolTable *localSymTab) const override; 354 bool operator==(const MIRConst &rhs) const override; 355 Clone(MemPool & memPool)356 MIRStr16Const *Clone(MemPool &memPool) const override 357 { 358 return memPool.New<MIRStr16Const>(*this); 359 } 360 GetValue()361 U16StrIdx GetValue() const 362 { 363 return value; 364 } 365 366 private: 367 static const PrimType kPrimType = PTY_ptr; 368 U16StrIdx value; 369 }; 370 371 class MIRFloatConst : public MIRConst { 372 public: 373 using value_type = float; MIRFloatConst(float val,MIRType & type)374 MIRFloatConst(float val, MIRType &type) : MIRConst(type, kConstFloatConst) 375 { 376 value.floatValue = val; 377 } 378 379 ~MIRFloatConst() = default; 380 SetFloatValue(float fvalue)381 void SetFloatValue(float fvalue) 382 { 383 value.floatValue = fvalue; 384 } 385 GetFloatValue()386 value_type GetFloatValue() const 387 { 388 return value.floatValue; 389 } 390 GetPrimType()391 static PrimType GetPrimType() 392 { 393 return kPrimType; 394 } 395 GetIntValue()396 int32 GetIntValue() const 397 { 398 return value.intValue; 399 } 400 GetValue()401 value_type GetValue() const 402 { 403 return GetFloatValue(); 404 } 405 406 void Dump(const MIRSymbolTable *localSymTab) const override; IsZero()407 bool IsZero() const override 408 { 409 return fabs(value.floatValue) <= 1e-6; 410 } 411 IsGeZero()412 bool IsGeZero() const 413 { 414 return value.floatValue >= 0; 415 } 416 IsNeg()417 bool IsNeg() const 418 { 419 return ((static_cast<uint32>(value.intValue) & 0x80000000) == 0x80000000); 420 } 421 IsOne()422 bool IsOne() const override 423 { 424 return fabs(value.floatValue - 1) <= 1e-6; 425 }; IsAllBitsOne()426 bool IsAllBitsOne() const 427 { 428 return fabs(value.floatValue + 1) <= 1e-6; 429 }; Neg()430 void Neg() override 431 { 432 value.floatValue = -value.floatValue; 433 } 434 435 bool operator==(const MIRConst &rhs) const override; 436 Clone(MemPool & memPool)437 MIRFloatConst *Clone(MemPool &memPool) const override 438 { 439 return memPool.New<MIRFloatConst>(*this); 440 } 441 442 private: 443 static const PrimType kPrimType = PTY_f32; 444 union { 445 value_type floatValue; 446 int32 intValue; 447 } value; 448 }; 449 450 class MIRDoubleConst : public MIRConst { 451 public: 452 using value_type = double; MIRDoubleConst(double val,MIRType & type)453 MIRDoubleConst(double val, MIRType &type) : MIRConst(type, kConstDoubleConst) 454 { 455 value.dValue = val; 456 } 457 458 ~MIRDoubleConst() = default; 459 GetIntLow32()460 uint32 GetIntLow32() const 461 { 462 auto unsignVal = static_cast<uint64>(value.intValue); 463 return static_cast<uint32>(unsignVal & 0xffffffff); 464 } 465 GetIntHigh32()466 uint32 GetIntHigh32() const 467 { 468 auto unsignVal = static_cast<uint64>(value.intValue); 469 return static_cast<uint32>((unsignVal & 0xffffffff00000000) >> k32BitSize); 470 } 471 GetIntValue()472 int64 GetIntValue() const 473 { 474 return value.intValue; 475 } 476 GetValue()477 value_type GetValue() const 478 { 479 return value.dValue; 480 } 481 GetPrimType()482 static PrimType GetPrimType() 483 { 484 return kPrimType; 485 } 486 487 void Dump(const MIRSymbolTable *localSymTab) const override; IsZero()488 bool IsZero() const override 489 { 490 return fabs(value.dValue) <= 1e-15; 491 } 492 IsGeZero()493 bool IsGeZero() const 494 { 495 return value.dValue >= 0; 496 } 497 IsNeg()498 bool IsNeg() const 499 { 500 return ((static_cast<uint64>(value.intValue) & 0x8000000000000000LL) == 0x8000000000000000LL); 501 } 502 IsOne()503 bool IsOne() const override 504 { 505 return fabs(value.dValue - 1) <= 1e-15; 506 }; IsAllBitsOne()507 bool IsAllBitsOne() const 508 { 509 return fabs(value.dValue + 1) <= 1e-15; 510 }; Neg()511 void Neg() override 512 { 513 value.dValue = -value.dValue; 514 } 515 516 bool operator==(const MIRConst &rhs) const override; 517 Clone(MemPool & memPool)518 MIRDoubleConst *Clone(MemPool &memPool) const override 519 { 520 return memPool.New<MIRDoubleConst>(*this); 521 } 522 523 private: 524 static const PrimType kPrimType = PTY_f64; 525 union { 526 value_type dValue; 527 int64 intValue; 528 } value; 529 }; 530 531 class MIRFloat128Const : public MIRConst { 532 public: MIRFloat128Const(const uint64 & val,MIRType & type)533 MIRFloat128Const(const uint64 &val, MIRType &type) : MIRConst(type, kConstFloat128Const) 534 { 535 value = &val; 536 } 537 538 ~MIRFloat128Const() = default; 539 GetIntValue()540 const uint64 *GetIntValue() const 541 { 542 return value; 543 } 544 GetPrimType()545 static PrimType GetPrimType() 546 { 547 return kPrimType; 548 } 549 IsZero()550 bool IsZero() const override 551 { 552 MIR_ASSERT(value && "value must not be nullptr!"); 553 return value[0] == 0 && value[1] == 0; 554 } 555 IsOne()556 bool IsOne() const override 557 { 558 MIR_ASSERT(value && "value must not be nullptr!"); 559 return value[0] == 0 && value[1] == 0x3FFF000000000000; 560 }; IsAllBitsOne()561 bool IsAllBitsOne() const 562 { 563 MIR_ASSERT(value && "value must not be nullptr!"); 564 return (value[0] == 0xffffffffffffffff && value[1] == 0xffffffffffffffff); 565 }; 566 bool operator==(const MIRConst &rhs) const override; 567 Clone(MemPool & memPool)568 MIRFloat128Const *Clone(MemPool &memPool) const override 569 { 570 auto *res = memPool.New<MIRFloat128Const>(*this); 571 return res; 572 } 573 574 void Dump(const MIRSymbolTable *localSymTab) const override; 575 576 private: 577 static const PrimType kPrimType = PTY_f128; 578 // value[0]: Low 64 bits; value[1]: High 64 bits. 579 const uint64 *value; 580 }; 581 582 class MIRAggConst : public MIRConst { 583 public: MIRAggConst(MIRModule & mod,MIRType & type)584 MIRAggConst(MIRModule &mod, MIRType &type) 585 : MIRConst(type, kConstAggConst), 586 constVec(mod.GetMPAllocator().Adapter()), 587 fieldIdVec(mod.GetMPAllocator().Adapter()) 588 { 589 } 590 591 ~MIRAggConst() = default; 592 GetAggConstElement(unsigned int fieldId)593 MIRConst *GetAggConstElement(unsigned int fieldId) 594 { 595 for (size_t i = 0; i < fieldIdVec.size(); ++i) { 596 if (fieldId == fieldIdVec[i]) { 597 return constVec[i]; 598 } 599 } 600 return nullptr; 601 } 602 SetFieldIdOfElement(uint32 index,uint32 fieldId)603 void SetFieldIdOfElement(uint32 index, uint32 fieldId) 604 { 605 DEBUG_ASSERT(index < fieldIdVec.size(), "index out of range"); 606 fieldIdVec[index] = fieldId; 607 } 608 GetConstVec()609 const MapleVector<MIRConst *> &GetConstVec() const 610 { 611 return constVec; 612 } 613 GetConstVec()614 MapleVector<MIRConst *> &GetConstVec() 615 { 616 return constVec; 617 } 618 GetConstVecItem(size_t index)619 const MIRConstPtr &GetConstVecItem(size_t index) const 620 { 621 CHECK_FATAL(index < constVec.size(), "index out of range"); 622 return constVec[index]; 623 } 624 GetConstVecItem(size_t index)625 MIRConstPtr &GetConstVecItem(size_t index) 626 { 627 CHECK_FATAL(index < constVec.size(), "index out of range"); 628 return constVec[index]; 629 } 630 SetConstVecItem(size_t index,MIRConst & st)631 void SetConstVecItem(size_t index, MIRConst &st) 632 { 633 CHECK_FATAL(index < constVec.size(), "index out of range"); 634 constVec[index] = &st; 635 } 636 GetFieldIdItem(size_t index)637 uint32 GetFieldIdItem(size_t index) const 638 { 639 DEBUG_ASSERT(index < fieldIdVec.size(), "index out of range"); 640 return fieldIdVec[index]; 641 } 642 SetItem(uint32 index,MIRConst * mirConst,uint32 fieldId)643 void SetItem(uint32 index, MIRConst *mirConst, uint32 fieldId) 644 { 645 CHECK_FATAL(index < constVec.size(), "index out of range"); 646 constVec[index] = mirConst; 647 fieldIdVec[index] = fieldId; 648 } 649 AddItem(MIRConst * mirConst,uint32 fieldId)650 void AddItem(MIRConst *mirConst, uint32 fieldId) 651 { 652 constVec.push_back(mirConst); 653 fieldIdVec.push_back(fieldId); 654 } 655 PushBack(MIRConst * elem)656 void PushBack(MIRConst *elem) 657 { 658 AddItem(elem, 0); 659 } 660 661 void Dump(const MIRSymbolTable *localSymTab) const override; 662 bool operator==(const MIRConst &rhs) const override; 663 Clone(MemPool & memPool)664 MIRAggConst *Clone(MemPool &memPool) const override 665 { 666 return memPool.New<MIRAggConst>(*this); 667 } 668 669 private: 670 MapleVector<MIRConst *> constVec; 671 MapleVector<uint32> fieldIdVec; 672 }; 673 674 // the const has one or more symbols 675 class MIRStConst : public MIRConst { 676 public: MIRStConst(MIRModule & mod,MIRType & type)677 MIRStConst(MIRModule &mod, MIRType &type) 678 : MIRConst(type, kConstStConst), 679 stVec(mod.GetMPAllocator().Adapter()), 680 stOffsetVec(mod.GetMPAllocator().Adapter()) 681 { 682 } 683 GetStVec()684 const MapleVector<MIRSymbol *> &GetStVec() const 685 { 686 return stVec; 687 } PushbackSymbolToSt(MIRSymbol * sym)688 void PushbackSymbolToSt(MIRSymbol *sym) 689 { 690 stVec.push_back(sym); 691 } 692 GetStVecItem(size_t index)693 MIRSymbol *GetStVecItem(size_t index) 694 { 695 CHECK_FATAL(index < stVec.size(), "array index out of range"); 696 return stVec[index]; 697 } 698 GetStOffsetVec()699 const MapleVector<uint32> &GetStOffsetVec() const 700 { 701 return stOffsetVec; 702 } PushbackOffsetToSt(uint32 offset)703 void PushbackOffsetToSt(uint32 offset) 704 { 705 stOffsetVec.push_back(offset); 706 } 707 GetStOffsetVecItem(size_t index)708 uint32 GetStOffsetVecItem(size_t index) const 709 { 710 CHECK_FATAL(index < stOffsetVec.size(), "array index out of range"); 711 return stOffsetVec[index]; 712 } 713 Clone(MemPool & memPool)714 MIRStConst *Clone(MemPool &memPool) const override 715 { 716 auto *res = memPool.New<MIRStConst>(*this); 717 return res; 718 } 719 720 ~MIRStConst() = default; 721 722 private: 723 MapleVector<MIRSymbol *> stVec; // symbols that in the st const 724 MapleVector<uint32> stOffsetVec; // symbols offset 725 }; 726 #endif // MIR_FEATURE_FULL 727 728 bool IsDivSafe(const MIRIntConst ÷nd, const MIRIntConst &divisor, PrimType pType); 729 730 } // namespace maple 731 732 #define LOAD_SAFE_CAST_FOR_MIR_CONST 733 #include "ir_safe_cast_traits.def" 734 735 #endif // MAPLE_IR_INCLUDE_MIR_CONST_H 736