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 &dividend, 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