• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &dividend, 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