• 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_TYPE_H
17 #define MAPLE_IR_INCLUDE_MIR_TYPE_H
18 #include <algorithm>
19 #include <array>
20 #include "prim_types.h"
21 #include "mir_pragma.h"
22 #include "mpl_logging.h"
23 #if MIR_FEATURE_FULL
24 #include "mempool.h"
25 #include "mempool_allocator.h"
26 #endif  // MIR_FEATURE_FULL
27 
28 namespace maple {
29 constexpr uint32 kTypeHashLength = 12289;   // hash length for mirtype, ref: planetmath.org/goodhashtableprimes
30 const std::string kRenameKeyWord = "_MNO";  // A static symbol name will be renamed as oriname_MNOxxx.
31 const uint8 kAlignBase = 0;                 // alignment base
32 using MIRTypePtr = MIRType *;
33 
34 constexpr size_t kMaxArrayDim = 20;
35 constexpr uint32 kInvalidFieldNum = UINT32_MAX;
36 constexpr size_t kInvalidSize = static_cast<size_t>(UINT64_MAX);
37 #if MIR_FEATURE_FULL
38 extern bool VerifyPrimType(PrimType primType1, PrimType primType2);  // verify if primType1 and primType2 match
39 extern PrimType GetExactPtrPrimType();                               // return either PTY_a64 or PTY_a32
40 extern uint32 GetPrimTypeSize(PrimType primType);                    // answer in bytes; 0 if unknown
41 extern uint32 GetPrimTypeP2Size(PrimType primType);                  // answer in bytes in power-of-two.
42 extern PrimType GetUnsignedPrimType(PrimType pty);                   // return unsigned version
43 #ifdef ARK_LITECG_DEBUG
44 extern const char *GetPrimTypeName(PrimType primType);
45 #endif
46 extern int64 MinValOfSignedInteger(PrimType primType);
47 extern PrimType GetVecElemPrimType(PrimType primType);
48 constexpr uint32 k0BitSize = 0;
49 constexpr uint32 k1BitSize = 1;
50 constexpr uint32 k2BitSize = 2;
51 constexpr uint32 k3BitSize = 3;
52 constexpr uint32 k4BitSize = 4;
53 constexpr uint32 k5BitSize = 5;
54 constexpr uint32 k7BitSize = 7;
55 constexpr uint32 k8BitSize = 8;
56 constexpr uint32 k9BitSize = 9;
57 constexpr uint32 k10BitSize = 10;
58 constexpr uint32 k16BitSize = 16;
59 constexpr uint32 k32BitSize = 32;
60 constexpr uint32 k64BitSize = 64;
61 constexpr uint32 k4BitShift = 2;  /* 4 is 1 << 2; */
62 constexpr uint32 k8BitShift = 3;  /* 8 is 1 << 3; */
63 constexpr uint32 k16BitShift = 4; /* 8 is 1 << 3; */
64 constexpr uint32 k2ByteSize = 2;
65 constexpr uint32 k3ByteSize = 3;
66 constexpr uint32 k4ByteSize = 4;
67 constexpr uint32 k7ByteSize = 7;
68 constexpr uint32 k8ByteSize = 8;
69 
GetPrimTypeBitSize(PrimType primType)70 inline uint32 GetPrimTypeBitSize(PrimType primType)
71 {
72     // 1 byte = 8 bits = 2^3 bits
73     return GetPrimTypeSize(primType) << k8BitShift;
74 }
75 
GetAlignedPrimTypeBitSize(PrimType primType)76 inline uint32 GetAlignedPrimTypeBitSize(PrimType primType)
77 {
78     auto size = GetPrimTypeBitSize(primType);
79     return size <= k32BitSize ? k32BitSize : k64BitSize;
80 }
81 
GetPrimTypeActualBitSize(PrimType primType)82 inline uint32 GetPrimTypeActualBitSize(PrimType primType)
83 {
84     // GetPrimTypeSize(PTY_u1) will return 1, so we take it as a special case
85     if (primType == PTY_u1) {
86         return 1;
87     }
88     // 1 byte = 8 bits = 2^3 bits
89     return GetPrimTypeSize(primType) << k8BitShift;
90 }
91 
92 #endif  // MIR_FEATURE_FULL
93 // return the same type with size increased to register size
94 PrimType GetRegPrimType(PrimType primType);
95 PrimType GetIntegerPrimTypeBySizeAndSign(size_t sizeBit, bool isSign);
96 
IsAddress(PrimitiveType primitiveType)97 inline bool IsAddress(PrimitiveType primitiveType)
98 {
99     return primitiveType.IsAddress();
100 }
101 
IsPossible64BitAddress(PrimType tp)102 inline bool IsPossible64BitAddress(PrimType tp)
103 {
104     return (tp == PTY_ptr || tp == PTY_ref || tp == PTY_u64 || tp == PTY_a64);
105 }
106 
IsPossible32BitAddress(PrimType tp)107 inline bool IsPossible32BitAddress(PrimType tp)
108 {
109     return (tp == PTY_ptr || tp == PTY_ref || tp == PTY_u32);
110 }
111 
112 
IsPrimitivePureScalar(PrimitiveType primitiveType)113 inline bool IsPrimitivePureScalar(PrimitiveType primitiveType)
114 {
115     return primitiveType.IsInteger() && !primitiveType.IsAddress();
116 }
117 
IsPrimitiveUnsigned(PrimitiveType primitiveType)118 inline bool IsPrimitiveUnsigned(PrimitiveType primitiveType)
119 {
120     return primitiveType.IsUnsigned();
121 }
122 
IsUnsignedInteger(PrimitiveType primitiveType)123 inline bool IsUnsignedInteger(PrimitiveType primitiveType)
124 {
125     return IsPrimitiveUnsigned(primitiveType) && primitiveType.IsInteger();
126 }
127 
IsSignedInteger(PrimitiveType primitiveType)128 inline bool IsSignedInteger(PrimitiveType primitiveType)
129 {
130     return !IsPrimitiveUnsigned(primitiveType) && primitiveType.IsInteger();
131 }
132 
IsPrimitiveInteger(PrimitiveType primitiveType)133 inline bool IsPrimitiveInteger(PrimitiveType primitiveType)
134 {
135     return primitiveType.IsInteger();
136 }
137 
IsPrimitiveFloat(PrimitiveType primitiveType)138 inline bool IsPrimitiveFloat(PrimitiveType primitiveType)
139 {
140     return primitiveType.IsFloat();
141 }
142 
IsPrimitiveScalar(PrimitiveType primitiveType)143 inline bool IsPrimitiveScalar(PrimitiveType primitiveType)
144 {
145     return primitiveType.IsInteger() || primitiveType.IsFloat() || primitiveType.IsSimple();
146 }
147 
IsPrimitivePoint(PrimitiveType primitiveType)148 inline bool IsPrimitivePoint(PrimitiveType primitiveType)
149 {
150     return primitiveType.IsPointer();
151 }
152 
153 bool IsNoCvtNeeded(PrimType toType, PrimType fromType);
154 
155 uint8 GetPointerSize();
156 PrimType GetLoweredPtrType();
157 
IsRefOrPtrAssign(PrimType toType,PrimType fromType)158 inline bool IsRefOrPtrAssign(PrimType toType, PrimType fromType)
159 {
160     return (toType == PTY_ref && fromType == PTY_ptr) || (toType == PTY_ptr && fromType == PTY_ref);
161 }
162 
163 enum MIRTypeKind : std::uint8_t {
164     kTypeScalar,
165     kTypeArray,
166     kTypePointer,
167     kTypeFunction,
168     kTypeVoid,
169     kTypeByName,          // type definition not yet seen
170 };
171 
172 enum AttrKind : unsigned {
173 #define TYPE_ATTR
174 #define ATTR(STR) ATTR_##STR,
175 #include "all_attributes.def"
176 #undef ATTR
177 #undef TYPE_ATTR
178 };
179 
180 class AttrBoundary {
181 public:
182     AttrBoundary() = default;
183     ~AttrBoundary() = default;
184 
185     bool operator==(const AttrBoundary &tA) const
186     {
187         return lenExprHash == tA.lenExprHash && lenParamIdx == tA.lenParamIdx && isBytedLen == tA.isBytedLen;
188     }
189 
190     bool operator!=(const AttrBoundary &tA) const
191     {
192         return !(*this == tA);
193     }
194 
195     bool operator<(const AttrBoundary &tA) const
196     {
197         return lenExprHash < tA.lenExprHash && lenParamIdx < tA.lenParamIdx &&
198                static_cast<int>(isBytedLen) < static_cast<int>(tA.isBytedLen);
199     }
200 
SetLenExprHash(uint32 val)201     void SetLenExprHash(uint32 val)
202     {
203         lenExprHash = val;
204     }
205 
GetLenExprHash()206     uint32 GetLenExprHash() const
207     {
208         return lenExprHash;
209     }
210 
SetLenParamIdx(int8 idx)211     void SetLenParamIdx(int8 idx)
212     {
213         lenParamIdx = idx;
214     }
215 
GetLenParamIdx()216     int8 GetLenParamIdx() const
217     {
218         return lenParamIdx;
219     }
220 
SetIsBytedLen(bool flag)221     void SetIsBytedLen(bool flag)
222     {
223         isBytedLen = flag;
224     }
225 
IsBytedLen()226     bool IsBytedLen() const
227     {
228         return isBytedLen;
229     }
230 
Clear()231     void Clear()
232     {
233         lenExprHash = 0;
234         lenParamIdx = -1;
235         isBytedLen = false;
236     }
237 
238 private:
239     bool isBytedLen = false;
240     int8 lenParamIdx = -1;
241     uint32 lenExprHash = 0;
242 };
243 
244 class TypeAttrs {
245 public:
246     TypeAttrs() = default;
247     TypeAttrs(const TypeAttrs &ta) = default;
248     TypeAttrs &operator=(const TypeAttrs &t) = default;
249     ~TypeAttrs() = default;
250 
GetAlignValue()251     uint8 GetAlignValue() const
252     {
253         return attrAlign;
254     }
255 
SetAttrFlag(uint64 flag)256     void SetAttrFlag(uint64 flag)
257     {
258         attrFlag = flag;
259     }
260 
GetTypeAlignValue()261     uint8 GetTypeAlignValue() const
262     {
263         return attrTypeAlign;
264     }
265 
GetAttrFlag()266     uint64 GetAttrFlag() const
267     {
268         return attrFlag;
269     }
270 
SetAttr(AttrKind x)271     void SetAttr(AttrKind x)
272     {
273         attrFlag |= (1ULL << static_cast<unsigned int>(x));
274     }
275 
ResetAttr(AttrKind x)276     void ResetAttr(AttrKind x)
277     {
278         attrFlag &= ~(1ULL << static_cast<unsigned int>(x));
279     }
280 
GetAttr(AttrKind x)281     bool GetAttr(AttrKind x) const
282     {
283         return (attrFlag & (1ULL << static_cast<unsigned int>(x))) != 0;
284     }
285 
SetAlign(uint32 x)286     void SetAlign(uint32 x)
287     {
288         DEBUG_ASSERT((~(x - 1) & x) == x, "SetAlign called with non-power-of-2");
289         attrAlign = 0;
290         while (x != 1) {
291             x >>= 1;
292             ++attrAlign;
293         }
294     }
295 
GetAlign()296     uint32 GetAlign() const
297     {
298         if (attrAlign == 0) {
299             return 1;
300         }
301         uint32 res = 1;
302         uint32 exp = attrAlign;
303         do {
304             --exp;
305             res <<= 1;
306         } while (exp != 0);
307         return res;
308     }
309 
SetTypeAlign(uint32 x)310     void SetTypeAlign(uint32 x)
311     {
312         DEBUG_ASSERT((~(x - 1) & x) == x, "SetTypeAlign called with non-power-of-2");
313         attrTypeAlign = 0;
314         while (x != kAlignBase) {
315             x >>= 1;
316             ++attrTypeAlign;
317         }
318     }
319 
GetTypeAlign()320     uint32 GetTypeAlign() const
321     {
322         if (attrTypeAlign == 1) {  // align(1)
323             return 1;
324         }
325         constexpr uint32 square = 2;
326         uint32 res = 1;
327         uint32 exp = attrTypeAlign;
328         while (exp > 1) {  // calculate align(x)
329             --exp;
330             res *= square;
331         }
332         return res;
333     }
334 
335     bool operator==(const TypeAttrs &tA) const
336     {
337         return attrFlag == tA.attrFlag && attrAlign == tA.attrAlign && attrBoundary == tA.attrBoundary;
338     }
339 
340     bool operator!=(const TypeAttrs &tA) const
341     {
342         return !(*this == tA);
343     }
344 
345 #ifdef ARK_LITECG_DEBUG
346     void DumpAttributes() const;
347 #endif
348 
GetAttrBoundary()349     const AttrBoundary &GetAttrBoundary() const
350     {
351         return attrBoundary;
352     }
353 
GetAttrBoundary()354     AttrBoundary &GetAttrBoundary()
355     {
356         return attrBoundary;
357     }
358 
AddAttrBoundary(const AttrBoundary & attr)359     void AddAttrBoundary(const AttrBoundary &attr)
360     {
361         if (attr.GetLenExprHash() != 0) {
362             attrBoundary.SetLenExprHash(attr.GetLenExprHash());
363         }
364         if (attr.GetLenParamIdx() != -1) {
365             attrBoundary.SetLenParamIdx(attr.GetLenParamIdx());
366         }
367         if (attr.IsBytedLen()) {
368             attrBoundary.SetIsBytedLen(attr.IsBytedLen());
369         }
370     }
371 
SetPack(uint32 pack)372     void SetPack(uint32 pack)
373     {
374         attrPack = pack;
375     }
376 
GetPack()377     uint32 GetPack() const
378     {
379         return attrPack;
380     }
381 
IsPacked()382     bool IsPacked() const
383     {
384         return GetAttr(ATTR_pack);
385     }
386 
HasPack()387     bool HasPack() const
388     {
389         return GetAttr(ATTR_pack);
390     }
391 
IsTypedef()392     bool IsTypedef() const
393     {
394         return GetAttr(ATTR_typedef);
395     }
396 
GetOriginType()397     MIRType *GetOriginType() const
398     {
399         return originType;
400     }
401 
402 private:
403     uint64 attrFlag = 0;
404     uint8 attrAlign = 0;        // alignment in bytes is 2 to the power of attrAlign
405     uint8 attrTypeAlign = 0;    // alignment in bytes is 2 to the power of attrTypeAlign
406     uint32 attrPack = -1;       // -1 means inactive
407     AttrBoundary attrBoundary;  // boundary attr for EnhanceC
408     MIRType *originType = nullptr;
409 };
410 
411 enum FieldAttrKind {
412 #define FIELD_ATTR
413 #define ATTR(STR) FLDATTR_##STR,
414 #include "all_attributes.def"
415 #undef ATTR
416 #undef FIELD_ATTR
417 };
418 
419 enum StmtAttrKind : unsigned {
420 #define STMT_ATTR
421 #define ATTR(STR) STMTATTR_##STR,
422 #include "all_attributes.def"
423 #undef ATTR
424 #undef STMT_ATTR
425 };
426 
427 class StmtAttrs {
428 public:
429     StmtAttrs() = default;
430     StmtAttrs(const StmtAttrs &ta) = default;
431     StmtAttrs &operator=(const StmtAttrs &p) = default;
432     ~StmtAttrs() = default;
433 
434     void SetAttr(StmtAttrKind x, bool flag = true)
435     {
436         if (flag) {
437             attrFlag |= (1u << static_cast<unsigned int>(x));
438         } else {
439             attrFlag &= ~(1u << static_cast<unsigned int>(x));
440         }
441     }
442 
GetAttr(StmtAttrKind x)443     bool GetAttr(StmtAttrKind x) const
444     {
445         return (attrFlag & (1u << static_cast<unsigned int>(x))) != 0;
446     }
447 
GetTargetAttrFlag(StmtAttrKind x)448     uint32 GetTargetAttrFlag(StmtAttrKind x) const
449     {
450         return attrFlag & (1u << static_cast<unsigned int>(x));
451     }
452 
GetAttrFlag()453     uint32 GetAttrFlag() const
454     {
455         return attrFlag;
456     }
457 
AppendAttr(uint32 flag)458     void AppendAttr(uint32 flag)
459     {
460         attrFlag |= flag;
461     }
462 
Clear()463     void Clear()
464     {
465         attrFlag = 0;
466     }
467 
468 #ifdef ARK_LITECG_DEBUG
469     void DumpAttributes() const;
470 #endif
471 
472 private:
473     uint32 attrFlag = 0;
474 };
475 
476 enum FuncAttrKind : unsigned {
477 #define FUNC_ATTR
478 #define ATTR(STR) FUNCATTR_##STR,
479 #include "all_attributes.def"
480 #undef ATTR
481 #undef FUNC_ATTR
482 };
483 
484 class FuncAttrs {
485 public:
486     FuncAttrs() = default;
487     FuncAttrs(const FuncAttrs &ta) = default;
488     FuncAttrs &operator=(const FuncAttrs &p) = default;
489     ~FuncAttrs() = default;
490 
491     void SetAttr(FuncAttrKind x, bool unSet = false)
492     {
493         if (!unSet) {
494             attrFlag |= (1ULL << x);
495         } else {
496             attrFlag &= ~(1ULL << x);
497         }
498     }
499 
SetAliasFuncName(const std::string & name)500     void SetAliasFuncName(const std::string &name)
501     {
502         aliasFuncName = name;
503     }
504 
GetAliasFuncName()505     const std::string &GetAliasFuncName() const
506     {
507         return aliasFuncName;
508     }
509 
SetPrefixSectionName(const std::string & name)510     void SetPrefixSectionName(const std::string &name)
511     {
512         prefixSectionName = name;
513     }
514 
GetPrefixSectionName()515     const std::string &GetPrefixSectionName() const
516     {
517         return prefixSectionName;
518     }
519 
SetAttrFlag(uint64 flag)520     void SetAttrFlag(uint64 flag)
521     {
522         attrFlag = flag;
523     }
524 
GetAttrFlag()525     uint64 GetAttrFlag() const
526     {
527         return attrFlag;
528     }
529 
GetAttr(FuncAttrKind x)530     bool GetAttr(FuncAttrKind x) const
531     {
532         return (attrFlag & (1ULL << x)) != 0;
533     }
534 
535     bool operator==(const FuncAttrs &tA) const
536     {
537         return attrFlag == tA.attrFlag;
538     }
539 
540     bool operator!=(const FuncAttrs &tA) const
541     {
542         return !(*this == tA);
543     }
544 
545 #ifdef ARK_LITECG_DEBUG
546     void DumpAttributes() const;
547 #endif
548 
GetAttrBoundary()549     const AttrBoundary &GetAttrBoundary() const
550     {
551         return attrBoundary;
552     }
553 
GetAttrBoundary()554     AttrBoundary &GetAttrBoundary()
555     {
556         return attrBoundary;
557     }
558 
SetConstructorPriority(int priority)559     void SetConstructorPriority(int priority)
560     {
561         constructorPriority = priority;
562     }
563 
GetConstructorPriority()564     int GetConstructorPriority() const
565     {
566         return constructorPriority;
567     }
568 
SetDestructorPriority(int priority)569     void SetDestructorPriority(int priority)
570     {
571         destructorPriority = priority;
572     }
573 
GetDestructorPriority()574     int GetDestructorPriority() const
575     {
576         return destructorPriority;
577     }
578 
GetFrameResverdSlot()579     int GetFrameResverdSlot() const
580     {
581         return frameResverdSlot;
582     }
583 
SetFrameResverdSlot(int slot)584     void SetFrameResverdSlot(int slot)
585     {
586         SetAttr(FUNCATTR_frame_pointer);
587         frameResverdSlot = slot;
588     }
589 
SetFramePointer(std::string framePointer_)590     void SetFramePointer(std::string framePointer_)
591     {
592         SetAttr(FUNCATTR_frame_reserved_slots);
593         framePointer = framePointer_;
594     }
595 
596 private:
597     uint64 attrFlag = 0;
598     std::string aliasFuncName;
599     std::string prefixSectionName;
600     std::string framePointer;
601     AttrBoundary attrBoundary;     // ret boundary for EnhanceC
602     int constructorPriority = -1;  // 0~65535, -1 means inactive
603     int destructorPriority = -1;   // 0~65535, -1 means inactive
604     int frameResverdSlot = 0;
605 };
606 
607 #if MIR_FEATURE_FULL
608 constexpr size_t kShiftNumOfTypeKind = 8;
609 constexpr size_t kShiftNumOfNameStrIdx = 6;
610 constexpr int32 kOffsetUnknown = INT_MAX;
611 constexpr int32 kOffsetMax = (INT_MAX - 1);
612 constexpr int32 kOffsetMin = INT_MIN;
613 struct OffsetType {
OffsetTypeOffsetType614     explicit OffsetType(int64 offset)
615     {
616         Set(offset);
617     }
618 
OffsetTypeOffsetType619     OffsetType(const OffsetType &other) : val(other.val) {}
620 
621     ~OffsetType() = default;
622 
SetOffsetType623     void Set(int64 offsetVal)
624     {
625         val = (offsetVal >= kOffsetMin && offsetVal <= kOffsetMax) ? static_cast<int32>(offsetVal) : kOffsetUnknown;
626     }
627 
IsInvalidOffsetType628     bool IsInvalid() const
629     {
630         return val == kOffsetUnknown;
631     }
632 
633     OffsetType &operator=(const OffsetType &other)
634     {
635         val = other.val;
636         return *this;
637     }
638 
639     OffsetType operator+(int64 offset) const
640     {
641         if (this->IsInvalid() || OffsetType(offset).IsInvalid()) {
642             return InvalidOffset();
643         }
644         return OffsetType(val + offset);
645     }
646 
647     OffsetType operator+(OffsetType other) const
648     {
649         return other + val;
650     }
651 
652     void operator+=(int64 offset)
653     {
654         if (this->IsInvalid() || OffsetType(offset).IsInvalid()) {
655             val = kOffsetUnknown;
656             return;
657         }
658         Set(offset + val);
659     }
660 
661     void operator+=(OffsetType other)
662     {
663         this->operator+=(other.val);
664     }
665 
666     OffsetType operator-() const
667     {
668         if (this->IsInvalid()) {
669             return *this;
670         }
671         return OffsetType(-val);
672     }
673 
674     bool operator<(OffsetType other) const
675     {
676         return val < other.val;
677     }
678 
679     bool operator==(OffsetType other) const
680     {
681         return val == other.val;
682     }
683 
684     bool operator!=(OffsetType other) const
685     {
686         return val != other.val;
687     }
688 
InvalidOffsetOffsetType689     static OffsetType InvalidOffset()
690     {
691         return OffsetType(kOffsetUnknown);
692     }
693 
694     int32 val = kOffsetUnknown;
695 };
696 class MIRFuncType;
697 
698 class MIRType {
699 public:
MIRType(MIRTypeKind kind)700     MIRType(MIRTypeKind kind) : typeKind(kind) {}
701 
MIRType(MIRTypeKind kind,PrimType pType)702     MIRType(MIRTypeKind kind, PrimType pType) : typeKind(kind), primType(pType) {}
703 
MIRType(MIRTypeKind kind,GStrIdx strIdx)704     MIRType(MIRTypeKind kind, GStrIdx strIdx) : typeKind(kind), nameStrIdx(strIdx) {}
705 
MIRType(MIRTypeKind kind,PrimType pType,GStrIdx strIdx)706     MIRType(MIRTypeKind kind, PrimType pType, GStrIdx strIdx) : typeKind(kind), primType(pType), nameStrIdx(strIdx) {}
707 
708     virtual ~MIRType() = default;
709 #ifdef ARK_LITECG_DEBUG
710     virtual void Dump(int indent, bool dontUseName = false) const;
711     virtual void DumpAsCxx(int indent) const;
712 #endif
713     virtual bool EqualTo(const MIRType &mirType) const;
714 
CopyMIRTypeNode()715     virtual MIRType *CopyMIRTypeNode() const
716     {
717         return new MIRType(*this);
718     }
719 
GetPrimType()720     PrimType GetPrimType() const
721     {
722         return primType;
723     }
SetPrimType(const PrimType pt)724     void SetPrimType(const PrimType pt)
725     {
726         primType = pt;
727     }
728 
GetTypeIndex()729     TyIdx GetTypeIndex() const
730     {
731         return tyIdx;
732     }
SetTypeIndex(TyIdx idx)733     void SetTypeIndex(TyIdx idx)
734     {
735         tyIdx = idx;
736     }
737 
GetKind()738     MIRTypeKind GetKind() const
739     {
740         return typeKind;
741     }
SetMIRTypeKind(MIRTypeKind kind)742     void SetMIRTypeKind(MIRTypeKind kind)
743     {
744         typeKind = kind;
745     }
746 
IsNameIsLocal()747     bool IsNameIsLocal() const
748     {
749         return nameIsLocal;
750     }
SetNameIsLocal(bool flag)751     void SetNameIsLocal(bool flag)
752     {
753         nameIsLocal = flag;
754     }
755 
GetNameStrIdx()756     GStrIdx GetNameStrIdx() const
757     {
758         return nameStrIdx;
759     }
SetNameStrIdx(GStrIdx strIdx)760     void SetNameStrIdx(GStrIdx strIdx)
761     {
762         nameStrIdx = strIdx;
763     }
SetNameStrIdxItem(uint32 idx)764     void SetNameStrIdxItem(uint32 idx)
765     {
766         nameStrIdx.reset(idx);
767     }
768 
GetSize()769     virtual size_t GetSize() const
770     {
771         return GetPrimTypeSize(primType);
772     }
773 
GetAlign()774     virtual uint32 GetAlign() const
775     {
776         return GetPrimTypeSize(primType);
777     }
778 
GetUnadjustedAlign()779     virtual uint32 GetUnadjustedAlign() const
780     {
781         return GetPrimTypeSize(primType);
782     }
783 
HasVolatileField()784     virtual bool HasVolatileField() const
785     {
786         return false;
787     }
788 
HasTypeParam()789     virtual bool HasTypeParam() const
790     {
791         return false;
792     }
793 
794     bool IsVolatile(int fieldID) const;
795 
IsMIRPtrType()796     bool IsMIRPtrType() const
797     {
798         return typeKind == kTypePointer;
799     }
800 
IsMIRArrayType()801     bool IsMIRArrayType() const
802     {
803         return typeKind == kTypeArray;
804     }
805 
IsMIRFuncType()806     bool IsMIRFuncType() const
807     {
808         return typeKind == kTypeFunction;
809     }
810 
IsScalarType()811     bool IsScalarType() const
812     {
813         return typeKind == kTypeScalar;
814     }
815 
IsMIRTypeByName()816     bool IsMIRTypeByName() const
817     {
818         return typeKind == kTypeByName;
819     }
820 
GetHashIndex()821     virtual size_t GetHashIndex() const
822     {
823         constexpr uint8 idxShift = 2;
824         return ((static_cast<uint32>(primType) << idxShift) + (typeKind << kShiftNumOfTypeKind)) % kTypeHashLength;
825     }
826 
827 protected:
828     MIRTypeKind typeKind;
829     PrimType primType;
830     bool nameIsLocal = false;  // needed when printing the type name
831     TyIdx tyIdx {0};
832     GStrIdx nameStrIdx {0};  // name in global string table
833 };
834 
835 class MIRPtrType : public MIRType {
836 public:
MIRPtrType(TyIdx pTyIdx)837     explicit MIRPtrType(TyIdx pTyIdx) : MIRType(kTypePointer, PTY_ptr), pointedTyIdx(pTyIdx) {}
838 
MIRPtrType(TyIdx pTyIdx,PrimType pty)839     MIRPtrType(TyIdx pTyIdx, PrimType pty) : MIRType(kTypePointer, pty), pointedTyIdx(pTyIdx) {}
840 
MIRPtrType(PrimType primType,GStrIdx strIdx)841     MIRPtrType(PrimType primType, GStrIdx strIdx) : MIRType(kTypePointer, primType, strIdx), pointedTyIdx(0) {}
842 
843     ~MIRPtrType() override = default;
844 
CopyMIRTypeNode()845     MIRType *CopyMIRTypeNode() const override
846     {
847         return new MIRPtrType(*this);
848     }
849 
850     MIRType *GetPointedType() const;
851 
GetPointedTyIdx()852     TyIdx GetPointedTyIdx() const
853     {
854         return pointedTyIdx;
855     }
SetPointedTyIdx(TyIdx idx)856     void SetPointedTyIdx(TyIdx idx)
857     {
858         pointedTyIdx = idx;
859     }
860 
GetTypeAttrs()861     TypeAttrs &GetTypeAttrs()
862     {
863         return typeAttrs;
864     }
865 
GetTypeAttrs()866     const TypeAttrs &GetTypeAttrs() const
867     {
868         return typeAttrs;
869     }
870 
SetTypeAttrs(const TypeAttrs & attrs)871     void SetTypeAttrs(const TypeAttrs &attrs)
872     {
873         typeAttrs = attrs;
874     }
875 
876     bool EqualTo(const MIRType &type) const override;
877     bool HasTypeParam() const override;
878     bool IsPointedTypeVolatile(int fieldID) const;
879 #ifdef ARK_LITECG_DEBUG
880     void Dump(int indent, bool dontUseName = false) const override;
881 #endif
882     size_t GetSize() const override;
883     uint32 GetAlign() const override;
GetHashIndex()884     size_t GetHashIndex() const override
885     {
886         constexpr uint8 idxShift = 4;
887         constexpr uint8 attrShift = 3;
888         size_t hIdx = (static_cast<size_t>(pointedTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
889         hIdx += (typeAttrs.GetAttrFlag() << attrShift) + typeAttrs.GetAlignValue();
890         return hIdx % kTypeHashLength;
891     }
IsFunctionPtr()892     bool IsFunctionPtr() const
893     {
894         MIRType *pointedType = GetPointedType();
895         if (pointedType->GetKind() == kTypeFunction) {
896             return true;
897         }
898         if (pointedType->GetKind() == kTypePointer) {
899             MIRPtrType *pointedPtrType = static_cast<MIRPtrType *>(pointedType);
900             return pointedPtrType->GetPointedType()->GetKind() == kTypeFunction;
901         }
902         return false;
903     }
904 
905     MIRFuncType *GetPointedFuncType() const;
906 
907 #ifdef ARK_LITECG_DEBUG
908     bool PointsToConstString() const;
909 #endif
910 
911 private:
912     TyIdx pointedTyIdx;
913     TypeAttrs typeAttrs;
914 };
915 
916 class MIRArrayType : public MIRType {
917 public:
MIRArrayType()918     MIRArrayType() : MIRType(kTypeArray) {}
MIRArrayType(GStrIdx strIdx)919     explicit MIRArrayType(GStrIdx strIdx) : MIRType(kTypeArray, strIdx) {}
920 
MIRArrayType(TyIdx eTyIdx,const std::vector<uint64> & sizeArray)921     MIRArrayType(TyIdx eTyIdx, const std::vector<uint64> &sizeArray)
922         : MIRType(kTypeArray), eTyIdx(eTyIdx), dim(sizeArray.size())
923     {
924         for (size_t i = 0; i < kMaxArrayDim; ++i) {
925             this->sizeArray[i] = (i < dim) ? sizeArray[i] : 0;
926         }
927     }
928 
929     MIRArrayType(const MIRArrayType &pat) = default;
930     MIRArrayType &operator=(const MIRArrayType &p) = default;
931     ~MIRArrayType() override = default;
932 
GetElemTyIdx()933     TyIdx GetElemTyIdx() const
934     {
935         return eTyIdx;
936     }
SetElemTyIdx(TyIdx idx)937     void SetElemTyIdx(TyIdx idx)
938     {
939         eTyIdx = idx;
940     }
941 
GetSizeArrayItem(uint32 n)942     uint64 GetSizeArrayItem(uint32 n) const
943     {
944         CHECK_FATAL((n >= 0 && n < kMaxArrayDim), "out of bound of array!");
945         return sizeArray[n];
946     }
SetSizeArrayItem(uint32 idx,uint64 value)947     void SetSizeArrayItem(uint32 idx, uint64 value)
948     {
949         CHECK_FATAL((idx >= 0 && idx < kMaxArrayDim), "out of bound of array!");
950         sizeArray[idx] = value;
951     }
952 
IsIncompleteArray()953     bool IsIncompleteArray() const
954     {
955         return typeAttrs.GetAttr(ATTR_incomplete_array);
956     }
957 
958     bool EqualTo(const MIRType &type) const override;
959 
GetDim()960     uint16 GetDim() const
961     {
962         return dim;
963     }
SetDim(uint16 newDim)964     void SetDim(uint16 newDim)
965     {
966         this->dim = newDim;
967     }
968 
GetTypeAttrs()969     const TypeAttrs &GetTypeAttrs() const
970     {
971         return typeAttrs;
972     }
973 
GetTypeAttrs()974     TypeAttrs &GetTypeAttrs()
975     {
976         return typeAttrs;
977     }
978 
SetTypeAttrs(const TypeAttrs & attrs)979     void SetTypeAttrs(const TypeAttrs &attrs)
980     {
981         typeAttrs = attrs;
982     }
983 
984     MIRType *GetElemType() const;
985 
CopyMIRTypeNode()986     MIRType *CopyMIRTypeNode() const override
987     {
988         return new MIRArrayType(*this);
989     }
990 
HasTypeParam()991     bool HasTypeParam() const override
992     {
993         return GetElemType()->HasTypeParam();
994     }
995 #ifdef ARK_LITECG_DEBUG
996     void Dump(int indent, bool dontUseName) const override;
997 #endif
998     size_t GetSize() const override;
999     uint32 GetAlign() const override;
1000 
GetHashIndex()1001     size_t GetHashIndex() const override
1002     {
1003         constexpr uint8 idxShift = 2;
1004         size_t hIdx = (static_cast<size_t>(eTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
1005         for (size_t i = 0; i < dim; ++i) {
1006             CHECK_FATAL(i < kMaxArrayDim, "array index out of range");
1007             hIdx += (sizeArray[i] << i);
1008         }
1009         constexpr uint8 attrShift = 3;
1010         hIdx += (typeAttrs.GetAttrFlag() << attrShift) + typeAttrs.GetAlignValue();
1011         return hIdx % kTypeHashLength;
1012     }
1013 
1014 #ifdef ARK_LITECG_DEBUG
1015     size_t ElemNumber() const;
1016 #endif
1017 
1018 private:
1019     TyIdx eTyIdx {0};
1020     uint16 dim = 0;
1021     std::array<uint64, kMaxArrayDim> sizeArray {{0}};
1022     TypeAttrs typeAttrs;
1023     mutable size_t size = kInvalidSize;
1024 };
1025 
1026 using TyidxFuncAttrPair = std::pair<TyIdx, FuncAttrs>;
1027 using MethodPair = std::pair<StIdx, TyidxFuncAttrPair>;
1028 using MethodVector = std::vector<MethodPair>;
1029 using MethodPtrVector = std::vector<MethodPair *>;
1030 using MIREncodedArray = std::vector<EncodedValue>;
1031 class GenericDeclare;
1032 class AnnotationType;
1033 class GenericType;
1034 
1035 class MIRFuncType : public MIRType {
1036 public:
MIRFuncType()1037     MIRFuncType() : MIRType(kTypeFunction, PTY_ptr) {}
1038 
MIRFuncType(const GStrIdx & strIdx)1039     explicit MIRFuncType(const GStrIdx &strIdx) : MIRType(kTypeFunction, PTY_ptr, strIdx) {}
1040 
MIRFuncType(const TyIdx & retTyIdx,const std::vector<TyIdx> & vecTy,const std::vector<TypeAttrs> & vecAt,const TypeAttrs & retAttrsIn)1041     MIRFuncType(const TyIdx &retTyIdx, const std::vector<TyIdx> &vecTy, const std::vector<TypeAttrs> &vecAt,
1042                 const TypeAttrs &retAttrsIn)
1043         : MIRType(kTypeFunction, PTY_ptr),
1044           retTyIdx(retTyIdx),
1045           paramTypeList(vecTy),
1046           paramAttrsList(vecAt),
1047           retAttrs(retAttrsIn)
1048     {
1049     }
1050 
1051     ~MIRFuncType() override = default;
1052 
1053     bool EqualTo(const MIRType &type) const override;
CopyMIRTypeNode()1054     MIRType *CopyMIRTypeNode() const override
1055     {
1056         return new MIRFuncType(*this);
1057     }
1058 #ifdef ARK_LITECG_DEBUG
1059     void Dump(int indent, bool dontUseName = false) const override;
1060 #endif
GetSize()1061     size_t GetSize() const override
1062     {
1063         return 0;
1064     }  // size unknown
1065 
GetRetTyIdx()1066     TyIdx GetRetTyIdx() const
1067     {
1068         return retTyIdx;
1069     }
1070 
SetRetTyIdx(TyIdx idx)1071     void SetRetTyIdx(TyIdx idx)
1072     {
1073         retTyIdx = idx;
1074     }
1075 
GetParamTypeList()1076     const std::vector<TyIdx> &GetParamTypeList() const
1077     {
1078         return paramTypeList;
1079     }
1080 
GetParamTypeList()1081     std::vector<TyIdx> &GetParamTypeList()
1082     {
1083         return paramTypeList;
1084     }
1085 
GetNthParamType(size_t i)1086     TyIdx GetNthParamType(size_t i) const
1087     {
1088         DEBUG_ASSERT(i < paramTypeList.size(), "array index out of range");
1089         return paramTypeList[i];
1090     }
1091 
SetParamTypeList(const std::vector<TyIdx> & list)1092     void SetParamTypeList(const std::vector<TyIdx> &list)
1093     {
1094         paramTypeList.clear();
1095         (void)paramTypeList.insert(paramTypeList.begin(), list.begin(), list.end());
1096     }
1097 
GetParamAttrsList()1098     const std::vector<TypeAttrs> &GetParamAttrsList() const
1099     {
1100         return paramAttrsList;
1101     }
1102 
GetParamAttrsList()1103     std::vector<TypeAttrs> &GetParamAttrsList()
1104     {
1105         return paramAttrsList;
1106     }
1107 
GetNthParamAttrs(size_t i)1108     const TypeAttrs &GetNthParamAttrs(size_t i) const
1109     {
1110         DEBUG_ASSERT(i < paramAttrsList.size(), "array index out of range");
1111         return paramAttrsList[i];
1112     }
1113 
GetNthParamAttrs(size_t i)1114     TypeAttrs &GetNthParamAttrs(size_t i)
1115     {
1116         DEBUG_ASSERT(i < paramAttrsList.size(), "array index out of range");
1117         return paramAttrsList[i];
1118     }
1119 
SetParamAttrsList(const std::vector<TypeAttrs> & list)1120     void SetParamAttrsList(const std::vector<TypeAttrs> &list)
1121     {
1122         paramAttrsList.clear();
1123         (void)paramAttrsList.insert(paramAttrsList.begin(), list.begin(), list.end());
1124     }
1125 
SetNthParamAttrs(size_t i,const TypeAttrs & attrs)1126     void SetNthParamAttrs(size_t i, const TypeAttrs &attrs)
1127     {
1128         DEBUG_ASSERT(i < paramAttrsList.size(), "array index out of range");
1129         paramAttrsList[i] = attrs;
1130     }
1131 
IsVarargs()1132     bool IsVarargs() const
1133     {
1134         return funcAttrs.GetAttr(FUNCATTR_varargs);
1135     }
1136 
SetVarArgs()1137     void SetVarArgs()
1138     {
1139         funcAttrs.SetAttr(FUNCATTR_varargs);
1140     }
1141 
FirstArgReturn()1142     bool FirstArgReturn() const
1143     {
1144         return funcAttrs.GetAttr(FUNCATTR_firstarg_return);
1145     }
1146 
SetFirstArgReturn()1147     void SetFirstArgReturn()
1148     {
1149         funcAttrs.SetAttr(FUNCATTR_firstarg_return);
1150     }
1151 
GetRetAttrs()1152     const TypeAttrs &GetRetAttrs() const
1153     {
1154         return retAttrs;
1155     }
1156 
GetRetAttrs()1157     TypeAttrs &GetRetAttrs()
1158     {
1159         return retAttrs;
1160     }
1161 
SetRetAttrs(const TypeAttrs & attrs)1162     void SetRetAttrs(const TypeAttrs &attrs)
1163     {
1164         retAttrs = attrs;
1165     }
1166 
GetHashIndex()1167     size_t GetHashIndex() const override
1168     {
1169         constexpr uint8 idxShift = 6;
1170         size_t hIdx = (static_cast<size_t>(retTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
1171         size_t size = paramTypeList.size();
1172         hIdx += (size ? (static_cast<size_t>(paramTypeList[0]) + size) : 0) << 4;  // shift bit is 4
1173         return hIdx % kTypeHashLength;
1174     }
1175 
1176 public:
1177     FuncAttrs funcAttrs;
1178 
1179 private:
1180     TyIdx retTyIdx {0};
1181     std::vector<TyIdx> paramTypeList;
1182     std::vector<TypeAttrs> paramAttrsList;
1183     TypeAttrs retAttrs;
1184 };
1185 
1186 class MIRTypeByName : public MIRType {
1187     // use nameStrIdx to store the name for both local and global
1188 public:
MIRTypeByName(GStrIdx gStrIdx)1189     explicit MIRTypeByName(GStrIdx gStrIdx) : MIRType(kTypeByName, PTY_void)
1190     {
1191         nameStrIdx = gStrIdx;
1192     }
1193 
1194     ~MIRTypeByName() override = default;
1195 
CopyMIRTypeNode()1196     MIRType *CopyMIRTypeNode() const override
1197     {
1198         return new MIRTypeByName(*this);
1199     }
1200 
1201     bool EqualTo(const MIRType &type) const override;
1202 #ifdef ARK_LITECG_DEBUG
1203     void Dump(int indent, bool dontUseName = false) const override;
1204 #endif
GetSize()1205     size_t GetSize() const override
1206     {
1207         return 0;
1208     }  // size unknown
1209 
GetHashIndex()1210     size_t GetHashIndex() const override
1211     {
1212         constexpr uint8 idxShift = 2;
1213         return ((static_cast<size_t>(nameStrIdx) << idxShift) + nameIsLocal + (typeKind << kShiftNumOfTypeKind)) %
1214                kTypeHashLength;
1215     }
1216 };
1217 // aarch64 specific
1218 bool IsHomogeneousAggregates(const MIRType &ty, PrimType &primType, size_t &elemNum, bool firstDepth = true);
1219 bool IsParamStructCopyToMemory(const MIRType &ty);
1220 #endif  // MIR_FEATURE_FULL
1221 }  // namespace maple
1222 
1223 #define LOAD_SAFE_CAST_FOR_MIR_TYPE
1224 #include "ir_safe_cast_traits.def"
1225 
1226 #endif  // MAPLE_IR_INCLUDE_MIR_TYPE_H
1227