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