• 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 
33 class FieldAttrs;  // circular dependency exists, no other choice
34 using TyIdxFieldAttrPair = std::pair<TyIdx, FieldAttrs>;
35 using FieldPair = std::pair<GStrIdx, TyIdxFieldAttrPair>;
36 using FieldVector = std::vector<FieldPair>;
37 using MIRTypePtr = MIRType *;
38 
39 constexpr size_t kMaxArrayDim = 20;
40 const std::string kJstrTypeName = "constStr";
41 constexpr uint32 kInvalidFieldNum = UINT32_MAX;
42 constexpr size_t kInvalidSize = static_cast<size_t>(UINT64_MAX);
43 #if MIR_FEATURE_FULL
44 extern bool VerifyPrimType(PrimType primType1, PrimType primType2);  // verify if primType1 and primType2 match
45 extern PrimType GetExactPtrPrimType();                               // return either PTY_a64 or PTY_a32
46 extern uint32 GetPrimTypeSize(PrimType primType);                    // answer in bytes; 0 if unknown
47 extern uint32 GetPrimTypeP2Size(PrimType primType);                  // answer in bytes in power-of-two.
48 extern PrimType GetSignedPrimType(PrimType pty);                     // return signed version
49 extern PrimType GetUnsignedPrimType(PrimType pty);                   // return unsigned version
50 extern uint32 GetVecEleSize(PrimType primType);                      // element size of each lane in vector
51 extern uint32 GetVecLanes(PrimType primType);                        // lane size if vector
52 extern const char *GetPrimTypeName(PrimType primType);
53 extern int64 MinValOfSignedInteger(PrimType primType);
54 extern PrimType GetVecElemPrimType(PrimType primType);
55 constexpr uint32 k0BitSize = 0;
56 constexpr uint32 k1BitSize = 1;
57 constexpr uint32 k2BitSize = 2;
58 constexpr uint32 k3BitSize = 3;
59 constexpr uint32 k4BitSize = 4;
60 constexpr uint32 k5BitSize = 5;
61 constexpr uint32 k7BitSize = 7;
62 constexpr uint32 k8BitSize = 8;
63 constexpr uint32 k9BitSize = 9;
64 constexpr uint32 k10BitSize = 10;
65 constexpr uint32 k16BitSize = 16;
66 constexpr uint32 k32BitSize = 32;
67 constexpr uint32 k64BitSize = 64;
68 constexpr uint32 k4BitShift = 2;  /* 4 is 1 << 2; */
69 constexpr uint32 k8BitShift = 3;  /* 8 is 1 << 3; */
70 constexpr uint32 k16BitShift = 4; /* 8 is 1 << 3; */
71 constexpr uint32 k2ByteSize = 2;
72 constexpr uint32 k3ByteSize = 3;
73 constexpr uint32 k4ByteSize = 4;
74 constexpr uint32 k7ByteSize = 7;
75 constexpr uint32 k8ByteSize = 8;
76 
GetPrimTypeBitSize(PrimType primType)77 inline uint32 GetPrimTypeBitSize(PrimType primType)
78 {
79     // 1 byte = 8 bits = 2^3 bits
80     return GetPrimTypeSize(primType) << k8BitShift;
81 }
82 
GetAlignedPrimTypeBitSize(PrimType primType)83 inline uint32 GetAlignedPrimTypeBitSize(PrimType primType)
84 {
85     auto size = GetPrimTypeBitSize(primType);
86     return size <= k32BitSize ? k32BitSize : k64BitSize;
87 }
88 
GetPrimTypeActualBitSize(PrimType primType)89 inline uint32 GetPrimTypeActualBitSize(PrimType primType)
90 {
91     // GetPrimTypeSize(PTY_u1) will return 1, so we take it as a special case
92     if (primType == PTY_u1) {
93         return 1;
94     }
95     // 1 byte = 8 bits = 2^3 bits
96     return GetPrimTypeSize(primType) << k8BitShift;
97 }
98 
99 #endif  // MIR_FEATURE_FULL
100 // return the same type with size increased to register size
101 PrimType GetRegPrimType(PrimType primType);
102 PrimType GetDynType(PrimType primType);
103 PrimType GetReg64PrimType(PrimType primType);
104 PrimType GetNonDynType(PrimType primType);
105 PrimType GetIntegerPrimTypeBySizeAndSign(size_t sizeBit, bool isSign);
106 
IsAddress(PrimitiveType primitiveType)107 inline bool IsAddress(PrimitiveType primitiveType)
108 {
109     return primitiveType.IsAddress();
110 }
111 
IsPossible64BitAddress(PrimType tp)112 inline bool IsPossible64BitAddress(PrimType tp)
113 {
114     return (tp == PTY_ptr || tp == PTY_ref || tp == PTY_u64 || tp == PTY_a64);
115 }
116 
IsPossible32BitAddress(PrimType tp)117 inline bool IsPossible32BitAddress(PrimType tp)
118 {
119     return (tp == PTY_ptr || tp == PTY_ref || tp == PTY_u32 || tp == PTY_a32);
120 }
121 
MustBeAddress(PrimType tp)122 inline bool MustBeAddress(PrimType tp)
123 {
124     return (tp == PTY_ptr || tp == PTY_ref || tp == PTY_a64 || tp == PTY_a32);
125 }
126 
IsInt128Ty(PrimType type)127 inline bool IsInt128Ty(PrimType type)
128 {
129     return type == PTY_u128 || type == PTY_i128;
130 }
131 
IsPrimitivePureScalar(PrimitiveType primitiveType)132 inline bool IsPrimitivePureScalar(PrimitiveType primitiveType)
133 {
134     return primitiveType.IsInteger() && !primitiveType.IsAddress() && !primitiveType.IsDynamic() &&
135            !primitiveType.IsVector();
136 }
137 
IsPrimitiveUnsigned(PrimitiveType primitiveType)138 inline bool IsPrimitiveUnsigned(PrimitiveType primitiveType)
139 {
140     return primitiveType.IsUnsigned();
141 }
142 
IsUnsignedInteger(PrimitiveType primitiveType)143 inline bool IsUnsignedInteger(PrimitiveType primitiveType)
144 {
145     return IsPrimitiveUnsigned(primitiveType) && primitiveType.IsInteger() && !primitiveType.IsDynamic();
146 }
147 
IsSignedInteger(PrimitiveType primitiveType)148 inline bool IsSignedInteger(PrimitiveType primitiveType)
149 {
150     return !IsPrimitiveUnsigned(primitiveType) && primitiveType.IsInteger() && !primitiveType.IsDynamic();
151 }
152 
IsPrimitiveInteger(PrimitiveType primitiveType)153 inline bool IsPrimitiveInteger(PrimitiveType primitiveType)
154 {
155     return primitiveType.IsInteger() && !primitiveType.IsDynamic() && !primitiveType.IsVector();
156 }
157 
IsPrimitiveDynType(PrimitiveType primitiveType)158 inline bool IsPrimitiveDynType(PrimitiveType primitiveType)
159 {
160     return primitiveType.IsDynamic();
161 }
162 
IsPrimitiveDynInteger(PrimitiveType primitiveType)163 inline bool IsPrimitiveDynInteger(PrimitiveType primitiveType)
164 {
165     return primitiveType.IsDynamic() && primitiveType.IsInteger();
166 }
167 
IsPrimitiveDynFloat(PrimitiveType primitiveType)168 inline bool IsPrimitiveDynFloat(PrimitiveType primitiveType)
169 {
170     return primitiveType.IsDynamic() && primitiveType.IsFloat();
171 }
172 
IsPrimitiveFloat(PrimitiveType primitiveType)173 inline bool IsPrimitiveFloat(PrimitiveType primitiveType)
174 {
175     return primitiveType.IsFloat() && !primitiveType.IsDynamic() && !primitiveType.IsVector();
176 }
177 
IsPrimitiveScalar(PrimitiveType primitiveType)178 inline bool IsPrimitiveScalar(PrimitiveType primitiveType)
179 {
180     return primitiveType.IsInteger() || primitiveType.IsFloat() ||
181            (primitiveType.IsDynamic() && !primitiveType.IsDynamicNone()) || primitiveType.IsSimple();
182 }
183 
IsPrimitiveValid(PrimitiveType primitiveType)184 inline bool IsPrimitiveValid(PrimitiveType primitiveType)
185 {
186     return IsPrimitiveScalar(primitiveType) && !primitiveType.IsDynamicAny();
187 }
188 
IsPrimitivePoint(PrimitiveType primitiveType)189 inline bool IsPrimitivePoint(PrimitiveType primitiveType)
190 {
191     return primitiveType.IsPointer();
192 }
193 
IsPrimitiveVector(PrimitiveType primitiveType)194 inline bool IsPrimitiveVector(PrimitiveType primitiveType)
195 {
196     return primitiveType.IsVector();
197 }
198 
IsPrimitiveVectorFloat(PrimitiveType primitiveType)199 inline bool IsPrimitiveVectorFloat(PrimitiveType primitiveType)
200 {
201     return primitiveType.IsVector() && primitiveType.IsFloat();
202 }
203 
IsPrimitiveVectorInteger(PrimitiveType primitiveType)204 inline bool IsPrimitiveVectorInteger(PrimitiveType primitiveType)
205 {
206     return primitiveType.IsVector() && primitiveType.IsInteger();
207 }
208 
IsPrimitiveUnSignedVector(const PrimitiveType & primitiveType)209 inline bool IsPrimitiveUnSignedVector(const PrimitiveType &primitiveType)
210 {
211     return IsPrimitiveUnsigned(primitiveType) && primitiveType.IsVector();
212 }
213 
214 bool IsNoCvtNeeded(PrimType toType, PrimType fromType);
215 bool NeedCvtOrRetype(PrimType origin, PrimType compared);
216 
217 uint8 GetPointerSize();
218 uint8 GetP2Size();
219 PrimType GetLoweredPtrType();
220 
IsRefOrPtrAssign(PrimType toType,PrimType fromType)221 inline bool IsRefOrPtrAssign(PrimType toType, PrimType fromType)
222 {
223     return (toType == PTY_ref && fromType == PTY_ptr) || (toType == PTY_ptr && fromType == PTY_ref);
224 }
225 
226 enum MIRTypeKind : std::uint8_t {
227     kTypeInvalid,
228     kTypeUnknown,
229     kTypeScalar,
230     kTypeBitField,
231     kTypeArray,
232     kTypeFArray,
233     kTypeJArray,
234     kTypeStruct,
235     kTypeUnion,
236     kTypeClass,
237     kTypeInterface,
238     kTypeStructIncomplete,
239     kTypeClassIncomplete,
240     kTypeConstString,
241     kTypeInterfaceIncomplete,
242     kTypePointer,
243     kTypeFunction,
244     kTypeVoid,
245     kTypeByName,          // type definition not yet seen
246     kTypeParam,           // to support j generics
247     kTypeInstantVector,   // represent a vector of instantiation pairs
248     kTypeGenericInstant,  // type to be formed by instantiation of a generic type
249 };
250 
251 enum AttrKind : unsigned {
252 #define TYPE_ATTR
253 #define ATTR(STR) ATTR_##STR,
254 #include "all_attributes.def"
255 #undef ATTR
256 #undef TYPE_ATTR
257 };
258 
259 class AttrBoundary {
260 public:
261     AttrBoundary() = default;
262     ~AttrBoundary() = default;
263 
264     bool operator==(const AttrBoundary &tA) const
265     {
266         return lenExprHash == tA.lenExprHash && lenParamIdx == tA.lenParamIdx && isBytedLen == tA.isBytedLen;
267     }
268 
269     bool operator!=(const AttrBoundary &tA) const
270     {
271         return !(*this == tA);
272     }
273 
274     bool operator<(const AttrBoundary &tA) const
275     {
276         return lenExprHash < tA.lenExprHash && lenParamIdx < tA.lenParamIdx &&
277                static_cast<int>(isBytedLen) < static_cast<int>(tA.isBytedLen);
278     }
279 
SetLenExprHash(uint32 val)280     void SetLenExprHash(uint32 val)
281     {
282         lenExprHash = val;
283     }
284 
GetLenExprHash()285     uint32 GetLenExprHash() const
286     {
287         return lenExprHash;
288     }
289 
SetLenParamIdx(int8 idx)290     void SetLenParamIdx(int8 idx)
291     {
292         lenParamIdx = idx;
293     }
294 
GetLenParamIdx()295     int8 GetLenParamIdx() const
296     {
297         return lenParamIdx;
298     }
299 
SetIsBytedLen(bool flag)300     void SetIsBytedLen(bool flag)
301     {
302         isBytedLen = flag;
303     }
304 
IsBytedLen()305     bool IsBytedLen() const
306     {
307         return isBytedLen;
308     }
309 
Clear()310     void Clear()
311     {
312         lenExprHash = 0;
313         lenParamIdx = -1;
314         isBytedLen = false;
315     }
316 
317 private:
318     bool isBytedLen = false;
319     int8 lenParamIdx = -1;
320     uint32 lenExprHash = 0;
321 };
322 
323 class TypeAttrs {
324 public:
325     TypeAttrs() = default;
326     TypeAttrs(const TypeAttrs &ta) = default;
327     TypeAttrs &operator=(const TypeAttrs &t) = default;
328     ~TypeAttrs() = default;
329 
SetAlignValue(uint8 align)330     void SetAlignValue(uint8 align)
331     {
332         attrAlign = align;
333     }
334 
GetAlignValue()335     uint8 GetAlignValue() const
336     {
337         return attrAlign;
338     }
339 
SetAttrFlag(uint64 flag)340     void SetAttrFlag(uint64 flag)
341     {
342         attrFlag = flag;
343     }
344 
SetTypeAlignValue(uint8 align)345     void SetTypeAlignValue(uint8 align)
346     {
347         attrTypeAlign = align;
348     }
349 
GetTypeAlignValue()350     uint8 GetTypeAlignValue() const
351     {
352         return attrTypeAlign;
353     }
354 
GetAttrFlag()355     uint64 GetAttrFlag() const
356     {
357         return attrFlag;
358     }
359 
SetAttr(AttrKind x)360     void SetAttr(AttrKind x)
361     {
362         attrFlag |= (1ULL << static_cast<unsigned int>(x));
363     }
364 
ResetAttr(AttrKind x)365     void ResetAttr(AttrKind x)
366     {
367         attrFlag &= ~(1ULL << static_cast<unsigned int>(x));
368     }
369 
GetAttr(AttrKind x)370     bool GetAttr(AttrKind x) const
371     {
372         return (attrFlag & (1ULL << static_cast<unsigned int>(x))) != 0;
373     }
374 
SetAlign(uint32 x)375     void SetAlign(uint32 x)
376     {
377         DEBUG_ASSERT((~(x - 1) & x) == x, "SetAlign called with non-power-of-2");
378         attrAlign = 0;
379         while (x != 1) {
380             x >>= 1;
381             ++attrAlign;
382         }
383     }
384 
GetAlign()385     uint32 GetAlign() const
386     {
387         if (attrAlign == 0) {
388             return 1;
389         }
390         uint32 res = 1;
391         uint32 exp = attrAlign;
392         do {
393             --exp;
394             res <<= 1;
395         } while (exp != 0);
396         return res;
397     }
398 
SetTypeAlign(uint32 x)399     void SetTypeAlign(uint32 x)
400     {
401         DEBUG_ASSERT((~(x - 1) & x) == x, "SetTypeAlign called with non-power-of-2");
402         attrTypeAlign = 0;
403         while (x != kAlignBase) {
404             x >>= 1;
405             ++attrTypeAlign;
406         }
407     }
408 
GetTypeAlign()409     uint32 GetTypeAlign() const
410     {
411         if (attrTypeAlign == 1) {  // align(1)
412             return 1;
413         }
414         constexpr uint32 square = 2;
415         uint32 res = 1;
416         uint32 exp = attrTypeAlign;
417         while (exp > 1) {  // calculate align(x)
418             --exp;
419             res *= square;
420         }
421         return res;
422     }
423 
424     bool operator==(const TypeAttrs &tA) const
425     {
426         return attrFlag == tA.attrFlag && attrAlign == tA.attrAlign && attrBoundary == tA.attrBoundary;
427     }
428 
429     bool operator!=(const TypeAttrs &tA) const
430     {
431         return !(*this == tA);
432     }
433 
434     void DumpAttributes() const;
435 
GetAttrBoundary()436     const AttrBoundary &GetAttrBoundary() const
437     {
438         return attrBoundary;
439     }
440 
GetAttrBoundary()441     AttrBoundary &GetAttrBoundary()
442     {
443         return attrBoundary;
444     }
445 
AddAttrBoundary(const AttrBoundary & attr)446     void AddAttrBoundary(const AttrBoundary &attr)
447     {
448         if (attr.GetLenExprHash() != 0) {
449             attrBoundary.SetLenExprHash(attr.GetLenExprHash());
450         }
451         if (attr.GetLenParamIdx() != -1) {
452             attrBoundary.SetLenParamIdx(attr.GetLenParamIdx());
453         }
454         if (attr.IsBytedLen()) {
455             attrBoundary.SetIsBytedLen(attr.IsBytedLen());
456         }
457     }
458 
SetPack(uint32 pack)459     void SetPack(uint32 pack)
460     {
461         attrPack = pack;
462     }
463 
GetPack()464     uint32 GetPack() const
465     {
466         return attrPack;
467     }
468 
IsPacked()469     bool IsPacked() const
470     {
471         return GetAttr(ATTR_pack);
472     }
473 
HasPack()474     bool HasPack() const
475     {
476         return GetAttr(ATTR_pack);
477     }
478 
IsTypedef()479     bool IsTypedef() const
480     {
481         return GetAttr(ATTR_typedef);
482     }
483 
SetOriginType(MIRType * basicType)484     void SetOriginType(MIRType *basicType)
485     {
486         originType = basicType;
487     }
488 
GetOriginType()489     MIRType *GetOriginType() const
490     {
491         return originType;
492     }
493 
494 private:
495     uint64 attrFlag = 0;
496     uint8 attrAlign = 0;        // alignment in bytes is 2 to the power of attrAlign
497     uint8 attrTypeAlign = 0;    // alignment in bytes is 2 to the power of attrTypeAlign
498     uint32 attrPack = -1;       // -1 means inactive
499     AttrBoundary attrBoundary;  // boundary attr for EnhanceC
500     MIRType *originType = nullptr;
501 };
502 
503 enum FieldAttrKind {
504 #define FIELD_ATTR
505 #define ATTR(STR) FLDATTR_##STR,
506 #include "all_attributes.def"
507 #undef ATTR
508 #undef FIELD_ATTR
509 };
510 
511 class FieldAttrs {
512 public:
513     FieldAttrs() = default;
514     FieldAttrs(const FieldAttrs &ta) = default;
515     FieldAttrs &operator=(const FieldAttrs &p) = default;
516     ~FieldAttrs() = default;
517 
SetAlignValue(uint8 align)518     void SetAlignValue(uint8 align)
519     {
520         attrAlign = align;
521     }
522 
GetAlignValue()523     uint8 GetAlignValue() const
524     {
525         return attrAlign;
526     }
527 
SetAttrFlag(uint32 flag)528     void SetAttrFlag(uint32 flag)
529     {
530         attrFlag = flag;
531     }
532 
GetAttrFlag()533     uint32 GetAttrFlag() const
534     {
535         return attrFlag;
536     }
537 
SetAttr(FieldAttrKind x)538     void SetAttr(FieldAttrKind x)
539     {
540         attrFlag |= (1u << static_cast<unsigned int>(x));
541     }
542 
GetAttr(FieldAttrKind x)543     bool GetAttr(FieldAttrKind x) const
544     {
545         return (attrFlag & (1u << static_cast<unsigned int>(x))) != 0;
546     }
547 
SetAlign(uint32 x)548     void SetAlign(uint32 x)
549     {
550         DEBUG_ASSERT((~(x - 1) & x) == x, "SetAlign called with non-power-of-2");
551         attrAlign = 0;
552         while (x != 1) {
553             x >>= 1;
554             ++attrAlign;
555         }
556     }
557 
GetAlign()558     uint32 GetAlign() const
559     {
560         return 1U << attrAlign;
561     }
562 
563     bool operator==(const FieldAttrs &tA) const
564     {
565         return attrFlag == tA.attrFlag && attrAlign == tA.attrAlign && attrBoundary == tA.attrBoundary;
566     }
567 
568     bool operator!=(const FieldAttrs &tA) const
569     {
570         return !(*this == tA);
571     }
572 
573     bool operator<(const FieldAttrs &tA) const
574     {
575         return attrFlag < tA.attrFlag && attrAlign < tA.attrAlign && attrBoundary < tA.attrBoundary;
576     }
577 
Clear()578     void Clear()
579     {
580         attrFlag = 0;
581         attrAlign = 0;
582         attrBoundary.Clear();
583     }
584 
585     void DumpAttributes() const;
586     TypeAttrs ConvertToTypeAttrs();
587 
GetAttrBoundary()588     const AttrBoundary &GetAttrBoundary() const
589     {
590         return attrBoundary;
591     }
592 
GetAttrBoundary()593     AttrBoundary &GetAttrBoundary()
594     {
595         return attrBoundary;
596     }
597 
IsPacked()598     bool IsPacked() const
599     {
600         return GetAttr(FLDATTR_pack);
601     }
602 
HasAligned()603     bool HasAligned() const
604     {
605         return GetAttr(FLDATTR_aligned) || GetAlign() != 1;
606     }
607 
608 private:
609     uint8 attrAlign = 0;  // alignment in bytes is 2 to the power of attrAlign
610     uint32 attrFlag = 0;
611     AttrBoundary attrBoundary;
612 };
613 
614 enum StmtAttrKind : unsigned {
615 #define STMT_ATTR
616 #define ATTR(STR) STMTATTR_##STR,
617 #include "all_attributes.def"
618 #undef ATTR
619 #undef STMT_ATTR
620 };
621 
622 class StmtAttrs {
623 public:
624     StmtAttrs() = default;
625     StmtAttrs(const StmtAttrs &ta) = default;
626     StmtAttrs &operator=(const StmtAttrs &p) = default;
627     ~StmtAttrs() = default;
628 
629     void SetAttr(StmtAttrKind x, bool flag = true)
630     {
631         if (flag) {
632             attrFlag |= (1u << static_cast<unsigned int>(x));
633         } else {
634             attrFlag &= ~(1u << static_cast<unsigned int>(x));
635         }
636     }
637 
GetAttr(StmtAttrKind x)638     bool GetAttr(StmtAttrKind x) const
639     {
640         return (attrFlag & (1u << static_cast<unsigned int>(x))) != 0;
641     }
642 
GetTargetAttrFlag(StmtAttrKind x)643     uint32 GetTargetAttrFlag(StmtAttrKind x) const
644     {
645         return attrFlag & (1u << static_cast<unsigned int>(x));
646     }
647 
GetAttrFlag()648     uint32 GetAttrFlag() const
649     {
650         return attrFlag;
651     }
652 
AppendAttr(uint32 flag)653     void AppendAttr(uint32 flag)
654     {
655         attrFlag |= flag;
656     }
657 
Clear()658     void Clear()
659     {
660         attrFlag = 0;
661     }
662 
663     void DumpAttributes() const;
664 
665 private:
666     uint32 attrFlag = 0;
667 };
668 
669 enum FuncAttrKind : unsigned {
670 #define FUNC_ATTR
671 #define ATTR(STR) FUNCATTR_##STR,
672 #include "all_attributes.def"
673 #undef ATTR
674 #undef FUNC_ATTR
675 };
676 
677 class FuncAttrs {
678 public:
679     FuncAttrs() = default;
680     FuncAttrs(const FuncAttrs &ta) = default;
681     FuncAttrs &operator=(const FuncAttrs &p) = default;
682     ~FuncAttrs() = default;
683 
684     void SetAttr(FuncAttrKind x, bool unSet = false)
685     {
686         if (!unSet) {
687             attrFlag |= (1ULL << x);
688         } else {
689             attrFlag &= ~(1ULL << x);
690         }
691     }
692 
SetAliasFuncName(const std::string & name)693     void SetAliasFuncName(const std::string &name)
694     {
695         aliasFuncName = name;
696     }
697 
GetAliasFuncName()698     const std::string &GetAliasFuncName() const
699     {
700         return aliasFuncName;
701     }
702 
SetPrefixSectionName(const std::string & name)703     void SetPrefixSectionName(const std::string &name)
704     {
705         prefixSectionName = name;
706     }
707 
GetPrefixSectionName()708     const std::string &GetPrefixSectionName() const
709     {
710         return prefixSectionName;
711     }
712 
SetAttrFlag(uint64 flag)713     void SetAttrFlag(uint64 flag)
714     {
715         attrFlag = flag;
716     }
717 
GetAttrFlag()718     uint64 GetAttrFlag() const
719     {
720         return attrFlag;
721     }
722 
GetAttr(FuncAttrKind x)723     bool GetAttr(FuncAttrKind x) const
724     {
725         return (attrFlag & (1ULL << x)) != 0;
726     }
727 
728     bool operator==(const FuncAttrs &tA) const
729     {
730         return attrFlag == tA.attrFlag;
731     }
732 
733     bool operator!=(const FuncAttrs &tA) const
734     {
735         return !(*this == tA);
736     }
737 
738     void DumpAttributes() const;
739 
GetAttrBoundary()740     const AttrBoundary &GetAttrBoundary() const
741     {
742         return attrBoundary;
743     }
744 
GetAttrBoundary()745     AttrBoundary &GetAttrBoundary()
746     {
747         return attrBoundary;
748     }
749 
SetConstructorPriority(int priority)750     void SetConstructorPriority(int priority)
751     {
752         constructorPriority = priority;
753     }
754 
GetConstructorPriority()755     int GetConstructorPriority() const
756     {
757         return constructorPriority;
758     }
759 
SetDestructorPriority(int priority)760     void SetDestructorPriority(int priority)
761     {
762         destructorPriority = priority;
763     }
764 
GetDestructorPriority()765     int GetDestructorPriority() const
766     {
767         return destructorPriority;
768     }
769 
GetFrameResverdSlot()770     int GetFrameResverdSlot() const
771     {
772         return frameResverdSlot;
773     }
774 
SetFrameResverdSlot(int slot)775     void SetFrameResverdSlot(int slot)
776     {
777         SetAttr(FUNCATTR_frame_pointer);
778         frameResverdSlot = slot;
779     }
780 
SetFramePointer(std::string framePointer_)781     void SetFramePointer(std::string framePointer_)
782     {
783         SetAttr(FUNCATTR_frame_reserved_slots);
784         framePointer = framePointer_;
785     }
786 
787 private:
788     uint64 attrFlag = 0;
789     std::string aliasFuncName;
790     std::string prefixSectionName;
791     std::string framePointer;
792     AttrBoundary attrBoundary;     // ret boundary for EnhanceC
793     int constructorPriority = -1;  // 0~65535, -1 means inactive
794     int destructorPriority = -1;   // 0~65535, -1 means inactive
795     int frameResverdSlot = 0;
796 };
797 
798 #if MIR_FEATURE_FULL
799 constexpr size_t kShiftNumOfTypeKind = 8;
800 constexpr size_t kShiftNumOfNameStrIdx = 6;
801 constexpr int32 kOffsetUnknown = INT_MAX;
802 constexpr int32 kOffsetMax = (INT_MAX - 1);
803 constexpr int32 kOffsetMin = INT_MIN;
804 struct OffsetType {
OffsetTypeOffsetType805     explicit OffsetType(int64 offset)
806     {
807         Set(offset);
808     }
809 
OffsetTypeOffsetType810     OffsetType(const OffsetType &other) : val(other.val) {}
811 
812     ~OffsetType() = default;
813 
SetOffsetType814     void Set(int64 offsetVal)
815     {
816         val = (offsetVal >= kOffsetMin && offsetVal <= kOffsetMax) ? static_cast<int32>(offsetVal) : kOffsetUnknown;
817     }
818 
IsInvalidOffsetType819     bool IsInvalid() const
820     {
821         return val == kOffsetUnknown;
822     }
823 
824     OffsetType &operator=(const OffsetType &other)
825     {
826         val = other.val;
827         return *this;
828     }
829 
830     OffsetType operator+(int64 offset) const
831     {
832         if (this->IsInvalid() || OffsetType(offset).IsInvalid()) {
833             return InvalidOffset();
834         }
835         return OffsetType(val + offset);
836     }
837 
838     OffsetType operator+(OffsetType other) const
839     {
840         return other + val;
841     }
842 
843     void operator+=(int64 offset)
844     {
845         if (this->IsInvalid() || OffsetType(offset).IsInvalid()) {
846             val = kOffsetUnknown;
847             return;
848         }
849         Set(offset + val);
850     }
851 
852     void operator+=(OffsetType other)
853     {
854         this->operator+=(other.val);
855     }
856 
857     OffsetType operator-() const
858     {
859         if (this->IsInvalid()) {
860             return *this;
861         }
862         return OffsetType(-val);
863     }
864 
865     bool operator<(OffsetType other) const
866     {
867         return val < other.val;
868     }
869 
870     bool operator==(OffsetType other) const
871     {
872         return val == other.val;
873     }
874 
875     bool operator!=(OffsetType other) const
876     {
877         return val != other.val;
878     }
879 
InvalidOffsetOffsetType880     static OffsetType InvalidOffset()
881     {
882         return OffsetType(kOffsetUnknown);
883     }
884 
885     int32 val = kOffsetUnknown;
886 };
887 
888 class MIRStructType;  // circular dependency exists, no other choice
889 class MIRFuncType;
890 
891 // if it is a bitfield, byteoffset gives the offset of the container for
892 // extracting the bitfield and bitoffset is with respect to the current byte
893 struct FieldInfo {
FieldInfoFieldInfo894     FieldInfo(uint32 byte, uint32 bit) : byteOffset(byte), bitOffset(bit) {}
FieldInfoFieldInfo895     FieldInfo(uint32 byte, uint32 bit, FieldPair &pair) : byteOffset(byte), bitOffset(bit), fieldPair(&pair) {}
896     uint32 byteOffset;
897     uint32 bitOffset;
898     FieldPair *fieldPair = nullptr;
899 };
900 
901 class MIRType {
902 public:
MIRType(MIRTypeKind kind,PrimType pType)903     MIRType(MIRTypeKind kind, PrimType pType) : typeKind(kind), primType(pType) {}
904 
MIRType(MIRTypeKind kind,PrimType pType,GStrIdx strIdx)905     MIRType(MIRTypeKind kind, PrimType pType, GStrIdx strIdx) : typeKind(kind), primType(pType), nameStrIdx(strIdx) {}
906 
907     virtual ~MIRType() = default;
908 
909     virtual void Dump(int indent, bool dontUseName = false) const;
910     virtual void DumpAsCxx(int indent) const;
911     virtual bool EqualTo(const MIRType &mirType) const;
IsStructType()912     virtual bool IsStructType() const
913     {
914         return false;
915     }
916 
CopyMIRTypeNode()917     virtual MIRType *CopyMIRTypeNode() const
918     {
919         return new MIRType(*this);
920     }
921 
GetPrimType()922     PrimType GetPrimType() const
923     {
924         return primType;
925     }
SetPrimType(const PrimType pt)926     void SetPrimType(const PrimType pt)
927     {
928         primType = pt;
929     }
930 
GetTypeIndex()931     TyIdx GetTypeIndex() const
932     {
933         return tyIdx;
934     }
SetTypeIndex(TyIdx idx)935     void SetTypeIndex(TyIdx idx)
936     {
937         tyIdx = idx;
938     }
939 
GetKind()940     MIRTypeKind GetKind() const
941     {
942         return typeKind;
943     }
SetMIRTypeKind(MIRTypeKind kind)944     void SetMIRTypeKind(MIRTypeKind kind)
945     {
946         typeKind = kind;
947     }
948 
IsNameIsLocal()949     bool IsNameIsLocal() const
950     {
951         return nameIsLocal;
952     }
SetNameIsLocal(bool flag)953     void SetNameIsLocal(bool flag)
954     {
955         nameIsLocal = flag;
956     }
957 
GetNameStrIdx()958     GStrIdx GetNameStrIdx() const
959     {
960         return nameStrIdx;
961     }
SetNameStrIdx(GStrIdx strIdx)962     void SetNameStrIdx(GStrIdx strIdx)
963     {
964         nameStrIdx = strIdx;
965     }
SetNameStrIdxItem(uint32 idx)966     void SetNameStrIdxItem(uint32 idx)
967     {
968         nameStrIdx.reset(idx);
969     }
970 
GetSize()971     virtual size_t GetSize() const
972     {
973         return GetPrimTypeSize(primType);
974     }
975 
GetAlign()976     virtual uint32 GetAlign() const
977     {
978         return GetPrimTypeSize(primType);
979     }
980 
GetUnadjustedAlign()981     virtual uint32 GetUnadjustedAlign() const
982     {
983         return GetPrimTypeSize(primType);
984     }
985 
HasVolatileField()986     virtual bool HasVolatileField() const
987     {
988         return false;
989     }
990 
HasTypeParam()991     virtual bool HasTypeParam() const
992     {
993         return false;
994     }
995 
IsIncomplete()996     virtual bool IsIncomplete() const
997     {
998         return typeKind == kTypeStructIncomplete || typeKind == kTypeClassIncomplete ||
999                typeKind == kTypeInterfaceIncomplete;
1000     }
1001 
1002     bool IsVolatile(int fieldID) const;
1003 
IsMIRPtrType()1004     bool IsMIRPtrType() const
1005     {
1006         return typeKind == kTypePointer;
1007     }
1008 
IsMIRStructType()1009     bool IsMIRStructType() const
1010     {
1011         return (typeKind == kTypeStruct) || (typeKind == kTypeStructIncomplete);
1012     }
1013 
IsMIRUnionType()1014     bool IsMIRUnionType() const
1015     {
1016         return typeKind == kTypeUnion;
1017     }
1018 
IsMIRClassType()1019     bool IsMIRClassType() const
1020     {
1021         return (typeKind == kTypeClass) || (typeKind == kTypeClassIncomplete);
1022     }
1023 
IsMIRInterfaceType()1024     bool IsMIRInterfaceType() const
1025     {
1026         return (typeKind == kTypeInterface) || (typeKind == kTypeInterfaceIncomplete);
1027     }
1028 
IsInstanceOfMIRStructType()1029     bool IsInstanceOfMIRStructType() const
1030     {
1031         return IsMIRStructType() || IsMIRClassType() || IsMIRInterfaceType();
1032     }
1033 
IsMIRJarrayType()1034     bool IsMIRJarrayType() const
1035     {
1036         return typeKind == kTypeJArray;
1037     }
1038 
IsMIRArrayType()1039     bool IsMIRArrayType() const
1040     {
1041         return typeKind == kTypeArray;
1042     }
1043 
IsMIRFuncType()1044     bool IsMIRFuncType() const
1045     {
1046         return typeKind == kTypeFunction;
1047     }
1048 
IsScalarType()1049     bool IsScalarType() const
1050     {
1051         return typeKind == kTypeScalar;
1052     }
1053 
IsMIRTypeByName()1054     bool IsMIRTypeByName() const
1055     {
1056         return typeKind == kTypeByName;
1057     }
1058 
IsMIRBitFieldType()1059     bool IsMIRBitFieldType() const
1060     {
1061         return typeKind == kTypeBitField;
1062     }
1063 
IsUnsafeType()1064     virtual bool IsUnsafeType() const
1065     {
1066         return false;
1067     }
IsVoidPointer()1068     virtual bool IsVoidPointer() const
1069     {
1070         return false;
1071     }
1072 
1073     bool ValidateClassOrInterface(const std::string &className, bool noWarning) const;
1074     bool IsOfSameType(MIRType &type);
1075     const std::string &GetName() const;
1076     virtual std::string GetMplTypeName() const;
1077     virtual std::string GetCompactMplTypeName() const;
1078     virtual bool PointsToConstString() const;
GetHashIndex()1079     virtual size_t GetHashIndex() const
1080     {
1081         constexpr uint8 idxShift = 2;
1082         return ((static_cast<uint32>(primType) << idxShift) + (typeKind << kShiftNumOfTypeKind)) % kTypeHashLength;
1083     }
1084 
HasFields()1085     virtual bool HasFields() const
1086     {
1087         return false;
1088     }
1089     // total number of field IDs the type is consisted of, excluding its own field ID
NumberOfFieldIDs()1090     virtual uint32 NumberOfFieldIDs() const
1091     {
1092         return 0;
1093     }
1094     // return any struct type directly embedded in this type
EmbeddedStructType()1095     virtual MIRStructType *EmbeddedStructType()
1096     {
1097         return nullptr;
1098     }
1099 
GetBitOffsetFromBaseAddr(FieldID fieldID)1100     virtual int64 GetBitOffsetFromBaseAddr(FieldID fieldID)
1101     {
1102         (void)fieldID;
1103         return 0;
1104     }
1105 
1106 protected:
1107     MIRTypeKind typeKind;
1108     PrimType primType;
1109     bool nameIsLocal = false;  // needed when printing the type name
1110     TyIdx tyIdx {0};
1111     GStrIdx nameStrIdx {0};  // name in global string table
1112 };
1113 
1114 class MIRPtrType : public MIRType {
1115 public:
MIRPtrType(TyIdx pTyIdx)1116     explicit MIRPtrType(TyIdx pTyIdx) : MIRType(kTypePointer, PTY_ptr), pointedTyIdx(pTyIdx) {}
1117 
MIRPtrType(TyIdx pTyIdx,PrimType pty)1118     MIRPtrType(TyIdx pTyIdx, PrimType pty) : MIRType(kTypePointer, pty), pointedTyIdx(pTyIdx) {}
1119 
MIRPtrType(PrimType primType,GStrIdx strIdx)1120     MIRPtrType(PrimType primType, GStrIdx strIdx) : MIRType(kTypePointer, primType, strIdx), pointedTyIdx(0) {}
1121 
1122     ~MIRPtrType() override = default;
1123 
CopyMIRTypeNode()1124     MIRType *CopyMIRTypeNode() const override
1125     {
1126         return new MIRPtrType(*this);
1127     }
1128 
1129     MIRType *GetPointedType() const;
1130 
GetPointedTyIdx()1131     TyIdx GetPointedTyIdx() const
1132     {
1133         return pointedTyIdx;
1134     }
SetPointedTyIdx(TyIdx idx)1135     void SetPointedTyIdx(TyIdx idx)
1136     {
1137         pointedTyIdx = idx;
1138     }
1139 
GetTypeAttrs()1140     TypeAttrs &GetTypeAttrs()
1141     {
1142         return typeAttrs;
1143     }
1144 
GetTypeAttrs()1145     const TypeAttrs &GetTypeAttrs() const
1146     {
1147         return typeAttrs;
1148     }
1149 
SetTypeAttrs(const TypeAttrs & attrs)1150     void SetTypeAttrs(const TypeAttrs &attrs)
1151     {
1152         typeAttrs = attrs;
1153     }
1154 
1155     bool EqualTo(const MIRType &type) const override;
1156 
1157     bool HasTypeParam() const override;
1158     bool IsPointedTypeVolatile(int fieldID) const;
1159     bool IsUnsafeType() const override;
1160     bool IsVoidPointer() const override;
1161 
1162     void Dump(int indent, bool dontUseName = false) const override;
1163     size_t GetSize() const override;
1164     uint32 GetAlign() const override;
1165     TyIdxFieldAttrPair GetPointedTyIdxFldAttrPairWithFieldID(FieldID fldId) const;
1166     TyIdx GetPointedTyIdxWithFieldID(FieldID fieldID) const;
GetHashIndex()1167     size_t GetHashIndex() const override
1168     {
1169         constexpr uint8 idxShift = 4;
1170         constexpr uint8 attrShift = 3;
1171         size_t hIdx = (static_cast<size_t>(pointedTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
1172         hIdx += (typeAttrs.GetAttrFlag() << attrShift) + typeAttrs.GetAlignValue();
1173         return hIdx % kTypeHashLength;
1174     }
IsFunctionPtr()1175     bool IsFunctionPtr() const
1176     {
1177         MIRType *pointedType = GetPointedType();
1178         if (pointedType->GetKind() == kTypeFunction) {
1179             return true;
1180         }
1181         if (pointedType->GetKind() == kTypePointer) {
1182             MIRPtrType *pointedPtrType = static_cast<MIRPtrType *>(pointedType);
1183             return pointedPtrType->GetPointedType()->GetKind() == kTypeFunction;
1184         }
1185         return false;
1186     }
1187 
1188     MIRFuncType *GetPointedFuncType() const;
1189 
1190     bool PointsToConstString() const override;
1191 
1192     std::string GetMplTypeName() const override;
1193 
1194     std::string GetCompactMplTypeName() const override;
1195 
1196 private:
1197     TyIdx pointedTyIdx;
1198     TypeAttrs typeAttrs;
1199 };
1200 
1201 class MIRArrayType : public MIRType {
1202 public:
MIRArrayType()1203     MIRArrayType() : MIRType(kTypeArray, PTY_agg) {}
MIRArrayType(GStrIdx strIdx)1204     explicit MIRArrayType(GStrIdx strIdx) : MIRType(kTypeArray, PTY_agg, strIdx) {}
1205 
MIRArrayType(TyIdx eTyIdx,const std::vector<uint64> & sizeArray)1206     MIRArrayType(TyIdx eTyIdx, const std::vector<uint64> &sizeArray)
1207         : MIRType(kTypeArray, PTY_agg), eTyIdx(eTyIdx), dim(sizeArray.size())
1208     {
1209         for (size_t i = 0; i < kMaxArrayDim; ++i) {
1210             this->sizeArray[i] = (i < dim) ? sizeArray[i] : 0;
1211         }
1212     }
1213 
1214     MIRArrayType(const MIRArrayType &pat) = default;
1215     MIRArrayType &operator=(const MIRArrayType &p) = default;
1216     ~MIRArrayType() override = default;
1217 
GetElemTyIdx()1218     TyIdx GetElemTyIdx() const
1219     {
1220         return eTyIdx;
1221     }
SetElemTyIdx(TyIdx idx)1222     void SetElemTyIdx(TyIdx idx)
1223     {
1224         eTyIdx = idx;
1225     }
1226 
GetSizeArrayItem(uint32 n)1227     uint64 GetSizeArrayItem(uint32 n) const
1228     {
1229         CHECK_FATAL((n >= 0 && n < kMaxArrayDim), "out of bound of array!");
1230         return sizeArray[n];
1231     }
SetSizeArrayItem(uint32 idx,uint64 value)1232     void SetSizeArrayItem(uint32 idx, uint64 value)
1233     {
1234         CHECK_FATAL((idx >= 0 && idx < kMaxArrayDim), "out of bound of array!");
1235         sizeArray[idx] = value;
1236     }
1237 
IsIncompleteArray()1238     bool IsIncompleteArray() const
1239     {
1240         return typeAttrs.GetAttr(ATTR_incomplete_array);
1241     }
1242 
1243     bool EqualTo(const MIRType &type) const override;
1244 
GetDim()1245     uint16 GetDim() const
1246     {
1247         return dim;
1248     }
SetDim(uint16 newDim)1249     void SetDim(uint16 newDim)
1250     {
1251         this->dim = newDim;
1252     }
1253 
GetTypeAttrs()1254     const TypeAttrs &GetTypeAttrs() const
1255     {
1256         return typeAttrs;
1257     }
1258 
GetTypeAttrs()1259     TypeAttrs &GetTypeAttrs()
1260     {
1261         return typeAttrs;
1262     }
1263 
SetTypeAttrs(const TypeAttrs & attrs)1264     void SetTypeAttrs(const TypeAttrs &attrs)
1265     {
1266         typeAttrs = attrs;
1267     }
1268 
1269     MIRType *GetElemType() const;
1270 
CopyMIRTypeNode()1271     MIRType *CopyMIRTypeNode() const override
1272     {
1273         return new MIRArrayType(*this);
1274     }
1275 
HasTypeParam()1276     bool HasTypeParam() const override
1277     {
1278         return GetElemType()->HasTypeParam();
1279     }
1280 
1281     void Dump(int indent, bool dontUseName) const override;
1282 
1283     size_t GetSize() const override;
1284     uint32 GetAlign() const override;
1285 
GetHashIndex()1286     size_t GetHashIndex() const override
1287     {
1288         constexpr uint8 idxShift = 2;
1289         size_t hIdx = (static_cast<size_t>(eTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
1290         for (size_t i = 0; i < dim; ++i) {
1291             CHECK_FATAL(i < kMaxArrayDim, "array index out of range");
1292             hIdx += (sizeArray[i] << i);
1293         }
1294         constexpr uint8 attrShift = 3;
1295         hIdx += (typeAttrs.GetAttrFlag() << attrShift) + typeAttrs.GetAlignValue();
1296         return hIdx % kTypeHashLength;
1297     }
1298 
GetBitOffsetFromBaseAddr(FieldID fieldID)1299     int64 GetBitOffsetFromBaseAddr(FieldID fieldID) override
1300     {
1301         (void)fieldID;
1302         return kOffsetUnknown;
1303     }
1304     int64 GetBitOffsetFromArrayAddress(std::vector<int64> &indexArray);
1305 
1306     std::string GetMplTypeName() const override;
1307     std::string GetCompactMplTypeName() const override;
1308     bool HasFields() const override;
1309     uint32 NumberOfFieldIDs() const override;
1310     MIRStructType *EmbeddedStructType() override;
1311     size_t ElemNumber() const;
1312 
1313 private:
1314     TyIdx eTyIdx {0};
1315     uint16 dim = 0;
1316     std::array<uint64, kMaxArrayDim> sizeArray {{0}};
1317     TypeAttrs typeAttrs;
1318     mutable uint32 fieldsNum = kInvalidFieldNum;
1319     mutable size_t size = kInvalidSize;
1320 };
1321 
1322 // flexible array type, must be last field of a top-level struct
1323 class MIRFarrayType : public MIRType {
1324 public:
MIRFarrayType()1325     MIRFarrayType() : MIRType(kTypeFArray, PTY_agg), elemTyIdx(TyIdx(0)) {};
1326 
MIRFarrayType(TyIdx elemTyIdx)1327     explicit MIRFarrayType(TyIdx elemTyIdx) : MIRType(kTypeFArray, PTY_agg), elemTyIdx(elemTyIdx) {}
1328 
MIRFarrayType(GStrIdx strIdx)1329     explicit MIRFarrayType(GStrIdx strIdx) : MIRType(kTypeFArray, PTY_agg, strIdx), elemTyIdx(TyIdx(0)) {}
1330 
1331     ~MIRFarrayType() override = default;
1332 
CopyMIRTypeNode()1333     MIRType *CopyMIRTypeNode() const override
1334     {
1335         return new MIRFarrayType(*this);
1336     };
1337 
1338     MIRType *GetElemType() const;
1339 
HasTypeParam()1340     bool HasTypeParam() const override
1341     {
1342         return GetElemType()->HasTypeParam();
1343     }
1344 
GetElemTyIdx()1345     TyIdx GetElemTyIdx() const
1346     {
1347         return elemTyIdx;
1348     }
SetElemtTyIdx(TyIdx idx)1349     void SetElemtTyIdx(TyIdx idx)
1350     {
1351         elemTyIdx = idx;
1352     }
1353 
1354     bool EqualTo(const MIRType &type) const override;
1355     void Dump(int indent, bool dontUseName = false) const override;
1356 
GetHashIndex()1357     size_t GetHashIndex() const override
1358     {
1359         constexpr uint8 idxShift = 5;
1360         return ((static_cast<size_t>(elemTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind)) % kTypeHashLength;
1361     }
1362 
1363     std::string GetMplTypeName() const override;
1364     std::string GetCompactMplTypeName() const override;
1365 
1366     bool HasFields() const override;
1367     uint32 NumberOfFieldIDs() const override;
1368     MIRStructType *EmbeddedStructType() override;
1369 
GetBitOffsetFromBaseAddr(FieldID fieldID)1370     int64 GetBitOffsetFromBaseAddr(FieldID fieldID) override
1371     {
1372         (void)fieldID;
1373         return kOffsetUnknown;
1374     }
1375 
1376     int64 GetBitOffsetFromArrayAddress(int64 arrayIndex);
1377 
1378 private:
1379     TyIdx elemTyIdx;
1380     mutable uint32 fieldsNum = kInvalidFieldNum;
1381 };
1382 
1383 using TyidxFuncAttrPair = std::pair<TyIdx, FuncAttrs>;
1384 using MethodPair = std::pair<StIdx, TyidxFuncAttrPair>;
1385 using MethodVector = std::vector<MethodPair>;
1386 using MethodPtrVector = std::vector<MethodPair *>;
1387 using MIREncodedArray = std::vector<EncodedValue>;
1388 class GenericDeclare;
1389 class AnnotationType;
1390 class GenericType;
1391 // used by kTypeStruct, kTypeStructIncomplete, kTypeUnion
1392 class MIRStructType : public MIRType {
1393 public:
MIRStructType(MIRTypeKind typeKind)1394     explicit MIRStructType(MIRTypeKind typeKind) : MIRType(typeKind, PTY_agg) {}
1395 
MIRStructType(MIRTypeKind typeKind,GStrIdx strIdx)1396     MIRStructType(MIRTypeKind typeKind, GStrIdx strIdx) : MIRType(typeKind, PTY_agg, strIdx) {}
1397 
1398     ~MIRStructType() override = default;
1399 
IsStructType()1400     bool IsStructType() const override
1401     {
1402         return true;
1403     }
1404 
GetFields()1405     FieldVector &GetFields()
1406     {
1407         return fields;
1408     }
GetFields()1409     const FieldVector &GetFields() const
1410     {
1411         return fields;
1412     }
SetFields(const FieldVector & newFields)1413     void SetFields(const FieldVector &newFields)
1414     {
1415         this->fields = newFields;
1416     }
1417 
GetFieldsElemt(size_t n)1418     const FieldPair &GetFieldsElemt(size_t n) const
1419     {
1420         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1421         return fields.at(n);
1422     }
1423 
GetFieldsElemt(size_t n)1424     FieldPair &GetFieldsElemt(size_t n)
1425     {
1426         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1427         return fields.at(n);
1428     }
1429 
GetFieldsSize()1430     size_t GetFieldsSize() const
1431     {
1432         return fields.size();
1433     }
1434 
GetFieldInferredTyIdx()1435     const std::vector<TyIdx> &GetFieldInferredTyIdx() const
1436     {
1437         return fieldInferredTyIdx;
1438     }
1439 
GetStaticFields()1440     FieldVector &GetStaticFields()
1441     {
1442         return staticFields;
1443     }
GetStaticFields()1444     const FieldVector &GetStaticFields() const
1445     {
1446         return staticFields;
1447     }
1448 
GetStaticFieldsPair(size_t i)1449     const FieldPair &GetStaticFieldsPair(size_t i) const
1450     {
1451         return staticFields.at(i);
1452     }
1453 
GetStaticFieldsGStrIdx(size_t i)1454     GStrIdx GetStaticFieldsGStrIdx(size_t i) const
1455     {
1456         return staticFields.at(i).first;
1457     }
1458 
GetParentFields()1459     FieldVector &GetParentFields()
1460     {
1461         return parentFields;
1462     }
SetParentFields(const FieldVector & newParentFields)1463     void SetParentFields(const FieldVector &newParentFields)
1464     {
1465         this->parentFields = newParentFields;
1466     }
GetParentFields()1467     const FieldVector &GetParentFields() const
1468     {
1469         return parentFields;
1470     }
GetParentFieldsElemt(size_t n)1471     const FieldPair &GetParentFieldsElemt(size_t n) const
1472     {
1473         DEBUG_ASSERT(n < parentFields.size(), "array index out of range");
1474         return parentFields.at(n);
1475     }
GetParentFieldsSize()1476     size_t GetParentFieldsSize() const
1477     {
1478         return parentFields.size();
1479     }
1480 
GetMethods()1481     MethodVector &GetMethods()
1482     {
1483         return methods;
1484     }
GetMethods()1485     const MethodVector &GetMethods() const
1486     {
1487         return methods;
1488     }
1489 
GetMethodsElement(size_t n)1490     const MethodPair &GetMethodsElement(size_t n) const
1491     {
1492         DEBUG_ASSERT(n < methods.size(), "array index out of range");
1493         return methods.at(n);
1494     }
1495 
GetVTableMethods()1496     MethodPtrVector &GetVTableMethods()
1497     {
1498         return vTableMethods;
1499     }
1500 
GetVTableMethodsElemt(size_t n)1501     const MethodPair *GetVTableMethodsElemt(size_t n) const
1502     {
1503         DEBUG_ASSERT(n < vTableMethods.size(), "array index out of range");
1504         return vTableMethods.at(n);
1505     }
1506 
GetVTableMethodsSize()1507     size_t GetVTableMethodsSize() const
1508     {
1509         return vTableMethods.size();
1510     }
1511 
GetItableMethods()1512     const MethodPtrVector &GetItableMethods() const
1513     {
1514         return iTableMethods;
1515     }
1516 
IsImported()1517     bool IsImported() const
1518     {
1519         return isImported;
1520     }
1521 
SetIsImported(bool flag)1522     void SetIsImported(bool flag)
1523     {
1524         isImported = flag;
1525     }
1526 
IsUsed()1527     bool IsUsed() const
1528     {
1529         return isUsed;
1530     }
1531 
SetIsUsed(bool flag)1532     void SetIsUsed(bool flag)
1533     {
1534         isUsed = flag;
1535     }
1536 
IsCPlusPlus()1537     bool IsCPlusPlus() const
1538     {
1539         return isCPlusPlus;
1540     }
1541 
SetIsCPlusPlus(bool flag)1542     void SetIsCPlusPlus(bool flag)
1543     {
1544         isCPlusPlus = flag;
1545     }
1546 
GetFieldGStrIdx(FieldID id)1547     GStrIdx GetFieldGStrIdx(FieldID id) const
1548     {
1549         const FieldPair &fieldPair = TraverseToField(id);
1550         return fieldPair.first;
1551     }
1552 
GetFieldTyIdxAttrPair(FieldID id)1553     const TyIdxFieldAttrPair GetFieldTyIdxAttrPair(FieldID id) const
1554     {
1555         return TraverseToField(id).second;
1556     }
1557 
GetTyidxFieldAttrPair(size_t n)1558     TyIdxFieldAttrPair GetTyidxFieldAttrPair(size_t n) const
1559     {
1560         return fields.at(n).second;
1561     }
1562 
GetFieldTyIdx(FieldID id)1563     TyIdx GetFieldTyIdx(FieldID id) const
1564     {
1565         const FieldPair &fieldPair = TraverseToField(id);
1566         return fieldPair.second.first;
1567     }
1568 
GetFieldAttrs(FieldID id)1569     FieldAttrs GetFieldAttrs(FieldID id) const
1570     {
1571         const FieldPair &fieldPair = TraverseToField(id);
1572         return fieldPair.second.second;
1573     }
1574 
GetFieldAttrs(GStrIdx fieldStrIdx)1575     FieldAttrs GetFieldAttrs(GStrIdx fieldStrIdx) const
1576     {
1577         const FieldPair &fieldPair = TraverseToField(fieldStrIdx);
1578         return fieldPair.second.second;
1579     }
1580 
IsFieldVolatile(FieldID id)1581     bool IsFieldVolatile(FieldID id) const
1582     {
1583         const FieldPair &fieldPair = TraverseToField(id);
1584         return fieldPair.second.second.GetAttr(FLDATTR_volatile);
1585     }
1586 
IsFieldFinal(FieldID id)1587     bool IsFieldFinal(FieldID id) const
1588     {
1589         const FieldPair &fieldPair = TraverseToField(id);
1590         return fieldPair.second.second.GetAttr(FLDATTR_final);
1591     }
1592 
IsFieldRCUnownedRef(FieldID id)1593     bool IsFieldRCUnownedRef(FieldID id) const
1594     {
1595         const FieldPair &fieldPair = TraverseToField(id);
1596         return fieldPair.second.second.GetAttr(FLDATTR_rcunowned);
1597     }
1598 
IsFieldRCWeak(FieldID id)1599     bool IsFieldRCWeak(FieldID id) const
1600     {
1601         const FieldPair &fieldPair = TraverseToField(id);
1602         return fieldPair.second.second.GetAttr(FLDATTR_rcweak);
1603     }
1604 
IsFieldRestrict(FieldID id)1605     bool IsFieldRestrict(FieldID id) const
1606     {
1607         const FieldPair &fieldPair = TraverseToField(id);
1608         return fieldPair.second.second.GetAttr(FLDATTR_restrict);
1609     }
1610 
IsOwnField(FieldID id)1611     bool IsOwnField(FieldID id) const
1612     {
1613         const FieldPair &fieldPair = TraverseToField(id);
1614         return std::find(fields.begin(), fields.end(), fieldPair) != fields.end();
1615     }
1616 
GetTypeAttrs()1617     TypeAttrs &GetTypeAttrs()
1618     {
1619         return typeAttrs;
1620     }
1621 
GetTypeAttrs()1622     const TypeAttrs &GetTypeAttrs() const
1623     {
1624         return typeAttrs;
1625     }
1626 
SetTypeAttrs(const TypeAttrs & attrs)1627     void SetTypeAttrs(const TypeAttrs &attrs)
1628     {
1629         typeAttrs = attrs;
1630     }
1631 
1632     bool HasVolatileField() const override;
1633     bool HasTypeParam() const override;
1634     bool EqualTo(const MIRType &type) const override;
CopyMIRTypeNode()1635     MIRType *CopyMIRTypeNode() const override
1636     {
1637         return new MIRStructType(*this);
1638     }
1639 
GetElemTyIdx(size_t n)1640     TyIdx GetElemTyIdx(size_t n) const
1641     {
1642         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1643         return fields.at(n).second.first;
1644     }
1645 
SetElemtTyIdxSimple(size_t n,TyIdx tyIdx)1646     void SetElemtTyIdxSimple(size_t n, TyIdx tyIdx)
1647     {
1648         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1649         fields.at(n).second.first = tyIdx;
1650     }
1651 
GetStaticElemtTyIdx(size_t n)1652     TyIdx GetStaticElemtTyIdx(size_t n) const
1653     {
1654         DEBUG_ASSERT(n < staticFields.size(), "array index out of range");
1655         return staticFields.at(n).second.first;
1656     }
1657 
SetStaticElemtTyIdx(size_t n,TyIdx tyIdx)1658     void SetStaticElemtTyIdx(size_t n, TyIdx tyIdx)
1659     {
1660         staticFields.at(n).second.first = tyIdx;
1661     }
1662 
SetMethodTyIdx(size_t n,TyIdx tyIdx)1663     void SetMethodTyIdx(size_t n, TyIdx tyIdx)
1664     {
1665         DEBUG_ASSERT(n < methods.size(), "array index out of range");
1666         methods.at(n).second.first = tyIdx;
1667     }
1668 
1669     MIRType *GetElemType(uint32 n) const;
1670 
1671     MIRType *GetFieldType(FieldID fieldID);
1672 
SetElemtTyIdx(size_t n,TyIdx tyIdx)1673     void SetElemtTyIdx(size_t n, TyIdx tyIdx)
1674     {
1675         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1676         fields.at(n).second = TyIdxFieldAttrPair(tyIdx, FieldAttrs());
1677     }
1678 
GetElemStrIdx(size_t n)1679     GStrIdx GetElemStrIdx(size_t n) const
1680     {
1681         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1682         return fields.at(n).first;
1683     }
1684 
SetElemStrIdx(size_t n,GStrIdx idx)1685     void SetElemStrIdx(size_t n, GStrIdx idx)
1686     {
1687         DEBUG_ASSERT(n < fields.size(), "array index out of range");
1688         fields.at(n).first = idx;
1689     }
1690 
SetElemInferredTyIdx(size_t n,TyIdx tyIdx)1691     void SetElemInferredTyIdx(size_t n, TyIdx tyIdx)
1692     {
1693         if (n >= fieldInferredTyIdx.size()) {
1694             (void)fieldInferredTyIdx.insert(fieldInferredTyIdx.end(), n + 1 - fieldInferredTyIdx.size(), kInitTyIdx);
1695         }
1696         DEBUG_ASSERT(n < fieldInferredTyIdx.size(), "array index out of range");
1697         fieldInferredTyIdx.at(n) = tyIdx;
1698     }
1699 
GetElemInferredTyIdx(size_t n)1700     TyIdx GetElemInferredTyIdx(size_t n)
1701     {
1702         if (n >= fieldInferredTyIdx.size()) {
1703             (void)fieldInferredTyIdx.insert(fieldInferredTyIdx.end(), n + 1 - fieldInferredTyIdx.size(), kInitTyIdx);
1704         }
1705         DEBUG_ASSERT(n < fieldInferredTyIdx.size(), "array index out of range");
1706         return fieldInferredTyIdx.at(n);
1707     }
1708 
1709     void DumpFieldsAndMethods(int indent, bool hasMethod) const;
1710     void Dump(int indent, bool dontUseName = false) const override;
1711 
SetComplete()1712     virtual void SetComplete()
1713     {
1714         typeKind = (typeKind == kTypeUnion) ? typeKind : kTypeStruct;
1715     }
1716 
1717     // only meaningful for MIRClassType and MIRInterface types
1718     bool IsLocal() const;
1719 
1720     size_t GetSize() const override;
1721     uint32 GetTypedefOriginalAlign() const;
1722     uint32 GetAlign() const override;
1723     uint32 GetAlignAux(bool toGetOriginal) const;
1724     uint32 GetUnadjustedAlign() const override;
1725 
GetHashIndex()1726     size_t GetHashIndex() const override
1727     {
1728         constexpr uint8 attrShift = 3;
1729         return ((static_cast<size_t>(nameStrIdx) << kShiftNumOfNameStrIdx) + (typeKind << kShiftNumOfTypeKind) +
1730                 ((typeAttrs.GetAttrFlag() << attrShift) + typeAttrs.GetAlignValue())) %
1731                kTypeHashLength;
1732     }
1733 
ClearContents()1734     virtual void ClearContents()
1735     {
1736         fields.clear();
1737         staticFields.clear();
1738         parentFields.clear();
1739         methods.clear();
1740         vTableMethods.clear();
1741         iTableMethods.clear();
1742         isImported = false;
1743         isUsed = false;
1744         hasVolatileField = false;
1745         hasVolatileFieldSet = false;
1746     }
1747 
GetInfo()1748     virtual const std::vector<MIRInfoPair> &GetInfo() const
1749     {
1750         CHECK_FATAL(false, "can not use GetInfo");
1751     }
1752 
GetInfoElemt(size_t)1753     virtual const MIRInfoPair &GetInfoElemt(size_t) const
1754     {
1755         CHECK_FATAL(false, "can not use GetInfoElemt");
1756     }
1757 
GetInfoIsString()1758     virtual const std::vector<bool> &GetInfoIsString() const
1759     {
1760         CHECK_FATAL(false, "can not use GetInfoIsString");
1761     }
1762 
GetInfoIsStringElemt(size_t)1763     virtual bool GetInfoIsStringElemt(size_t) const
1764     {
1765         CHECK_FATAL(false, "can not use GetInfoIsStringElemt");
1766     }
1767 
GetPragmaVec()1768     virtual const std::vector<MIRPragma *> &GetPragmaVec() const
1769     {
1770         CHECK_FATAL(false, "can not use GetPragmaVec");
1771     }
1772 
GetPragmaVec()1773     virtual std::vector<MIRPragma *> &GetPragmaVec()
1774     {
1775         CHECK_FATAL(false, "can not use GetPragmaVec");
1776     }
1777 
GetGenericDeclare()1778     std::vector<GenericDeclare *> &GetGenericDeclare()
1779     {
1780         return genericDeclare;
1781     }
1782 
AddClassGenericDeclare(GenericDeclare * gd)1783     void AddClassGenericDeclare(GenericDeclare *gd)
1784     {
1785         genericDeclare.push_back(gd);
1786     }
1787 
AddFieldGenericDeclare(const GStrIdx & g,AnnotationType * a)1788     void AddFieldGenericDeclare(const GStrIdx &g, AnnotationType *a)
1789     {
1790         if (fieldGenericDeclare.find(g) != fieldGenericDeclare.end()) {
1791             CHECK_FATAL(fieldGenericDeclare[g] == a, "MUST BE");
1792         }
1793         fieldGenericDeclare[g] = a;
1794     }
1795 
GetFieldGenericDeclare(const GStrIdx & g)1796     AnnotationType *GetFieldGenericDeclare(const GStrIdx &g)
1797     {
1798         if (fieldGenericDeclare.find(g) == fieldGenericDeclare.end()) {
1799             return nullptr;
1800         }
1801         return fieldGenericDeclare[g];
1802     }
1803 
AddInheritaceGeneric(GenericType * a)1804     void AddInheritaceGeneric(GenericType *a)
1805     {
1806         inheritanceGeneric.push_back(a);
1807     }
1808 
GetInheritanceGeneric()1809     std::vector<GenericType *> &GetInheritanceGeneric()
1810     {
1811         return inheritanceGeneric;
1812     }
1813 
GetStaticValue()1814     virtual const MIREncodedArray &GetStaticValue() const
1815     {
1816         CHECK_FATAL(false, "can not use GetStaticValue");
1817     }
1818 
PushbackMIRInfo(const MIRInfoPair &)1819     virtual void PushbackMIRInfo(const MIRInfoPair &)
1820     {
1821         CHECK_FATAL(false, "can not use PushbackMIRInfo");
1822     }
1823 
PushbackPragma(MIRPragma *)1824     virtual void PushbackPragma(MIRPragma *)
1825     {
1826         CHECK_FATAL(false, "can not use PushbackPragma");
1827     }
1828 
PushbackStaticValue(EncodedValue &)1829     virtual void PushbackStaticValue(EncodedValue &)
1830     {
1831         CHECK_FATAL(false, "can not use PushbackStaticValue");
1832     }
1833 
PushbackIsString(bool)1834     virtual void PushbackIsString(bool)
1835     {
1836         CHECK_FATAL(false, "can not use PushbackIsString");
1837     }
1838 
HasFields()1839     bool HasFields() const override
1840     {
1841         return true;
1842     }
1843     uint32 NumberOfFieldIDs() const override;
EmbeddedStructType()1844     MIRStructType *EmbeddedStructType() override
1845     {
1846         return this;
1847     }
1848 
1849     virtual FieldPair TraverseToFieldRef(FieldID &fieldID) const;
1850     std::string GetMplTypeName() const override;
1851     std::string GetCompactMplTypeName() const override;
1852     FieldPair TraverseToField(FieldID fieldID) const;
1853 
1854     int64 GetBitOffsetFromBaseAddr(FieldID fieldID) override;
1855 
1856     FieldInfo GetFieldOffsetFromBaseAddr(FieldID fieldID) const;
1857 
1858     bool HasPadding() const;
1859 
1860     bool HasZeroWidthBitField() const;
1861 
AddFieldLayout(const FieldInfo & info)1862     void AddFieldLayout(const FieldInfo &info)
1863     {
1864         fieldLayout.emplace_back(info);
1865     }
1866 
GetFieldLayout()1867     std::vector<FieldInfo> &GetFieldLayout()
1868     {
1869         if (!layoutComputed) {
1870             ComputeLayout();
1871         }
1872         return fieldLayout;
1873     }
1874 
1875     uint32 GetFieldTypeAlignByFieldPair(const FieldPair &fieldPair);
1876 
1877 protected:
1878     FieldVector fields {};
1879     std::vector<TyIdx> fieldInferredTyIdx {};
1880     FieldVector staticFields {};
1881     FieldVector parentFields {};       // fields belong to the ancestors not fully defined
1882     MethodVector methods {};           // for the list of member function prototypes
1883     MethodPtrVector vTableMethods {};  // the list of implmentation for all virtual functions for this type
1884     MethodPtrVector iTableMethods {};  // the list of all interface functions for this type; For classes, they are
1885     // implementation functions, For interfaces, they are abstact functions.
1886     // Weak indicates the actual definition is in another module.
1887     bool isImported = false;
1888     bool isUsed = false;
1889     bool isCPlusPlus = false;                  // empty struct in C++ has size 1 byte
1890     mutable bool hasVolatileField = false;     // for caching computed value
1891     mutable bool hasVolatileFieldSet = false;  // if true, just read hasVolatileField;
1892                                                // otherwise compute to initialize hasVolatileField
1893     std::vector<GenericDeclare *> genericDeclare;
1894     std::map<GStrIdx, AnnotationType *> fieldGenericDeclare;
1895     std::vector<GenericType *> inheritanceGeneric;
1896     TypeAttrs typeAttrs;
1897     mutable uint32 fieldsNum = kInvalidFieldNum;
1898     mutable std::vector<FieldInfo> fieldLayout;
1899     mutable size_t size = kInvalidSize;
1900 
1901     bool layoutComputed = false;
1902 
1903 private:
1904     FieldPair TraverseToField(GStrIdx fieldStrIdx) const;
1905     bool HasVolatileFieldInFields(const FieldVector &fieldsOfStruct) const;
1906     bool HasTypeParamInFields(const FieldVector &fieldsOfStruct) const;
1907     int64 GetBitOffsetFromUnionBaseAddr(FieldID fieldID);
1908     int64 GetBitOffsetFromStructBaseAddr(FieldID fieldID);
1909     void ComputeUnionLayout();
1910     void ComputeLayout();
1911 };
1912 
1913 class MIRJarrayType : public MIRFarrayType {
1914 public:
MIRJarrayType()1915     MIRJarrayType()
1916     {
1917         typeKind = kTypeJArray;
1918     };
1919 
MIRJarrayType(TyIdx elemTyIdx)1920     explicit MIRJarrayType(TyIdx elemTyIdx) : MIRFarrayType(elemTyIdx)
1921     {
1922         typeKind = kTypeJArray;
1923     }
1924 
MIRJarrayType(GStrIdx strIdx)1925     explicit MIRJarrayType(GStrIdx strIdx) : MIRFarrayType(strIdx)
1926     {
1927         typeKind = kTypeJArray;
1928     }
1929 
1930     ~MIRJarrayType() override = default;
1931 
CopyMIRTypeNode()1932     MIRType *CopyMIRTypeNode() const override
1933     {
1934         return new MIRJarrayType(*this);
1935     }
1936 
1937     MIRStructType *GetParentType();
1938 
IsPrimitiveArray()1939     bool IsPrimitiveArray()
1940     {
1941         if (jNameStrIdx == 0u) {
1942             DetermineName();
1943         }
1944         return fromPrimitive;
1945     }
1946 
GetDim()1947     int GetDim()
1948     {
1949         if (jNameStrIdx == 0u) {
1950             DetermineName();
1951         }
1952         return dim;
1953     }
1954 
GetHashIndex()1955     size_t GetHashIndex() const override
1956     {
1957         constexpr uint8 idxShift = 5;
1958         return ((static_cast<size_t>(GetElemTyIdx()) << idxShift) + (typeKind << kShiftNumOfTypeKind)) %
1959                kTypeHashLength;
1960     }
1961 
1962 private:
1963     void DetermineName();        // determine the internal name of this type
1964     TyIdx parentTyIdx {0};       // since Jarray is also an object, this is j.lang.Object
1965     GStrIdx jNameStrIdx {0};     // for internal j name of Jarray. nameStrIdx is used for other purpose
1966     bool fromPrimitive = false;  // the lowest dimension is primitive type
1967     int dim = 0;                 // the dimension if decidable at compile time. otherwise 0
1968 };
1969 
1970 // used by kTypeClass, kTypeClassIncomplete
1971 class MIRClassType : public MIRStructType {
1972 public:
MIRClassType(MIRTypeKind tKind)1973     explicit MIRClassType(MIRTypeKind tKind) : MIRStructType(tKind) {}
MIRClassType(MIRTypeKind tKind,GStrIdx strIdx)1974     MIRClassType(MIRTypeKind tKind, GStrIdx strIdx) : MIRStructType(tKind, strIdx) {}
1975     ~MIRClassType() override = default;
1976 
1977     bool EqualTo(const MIRType &type) const override;
1978 
CopyMIRTypeNode()1979     MIRType *CopyMIRTypeNode() const override
1980     {
1981         return new MIRClassType(*this);
1982     }
1983 
GetInfo()1984     const std::vector<MIRInfoPair> &GetInfo() const override
1985     {
1986         return info;
1987     }
PushbackMIRInfo(const MIRInfoPair & pair)1988     void PushbackMIRInfo(const MIRInfoPair &pair) override
1989     {
1990         info.push_back(pair);
1991     }
1992     uint32 GetInfo(const std::string &infoStr) const;
1993     uint32 GetInfo(GStrIdx strIdx) const;
GetInfoSize()1994     size_t GetInfoSize() const
1995     {
1996         return info.size();
1997     }
1998 
GetInfoElemt(size_t n)1999     const MIRInfoPair &GetInfoElemt(size_t n) const override
2000     {
2001         DEBUG_ASSERT(n < info.size(), "array index out of range");
2002         return info.at(n);
2003     }
2004 
GetInfoIsString()2005     const std::vector<bool> &GetInfoIsString() const override
2006     {
2007         return infoIsString;
2008     }
2009 
PushbackIsString(bool isString)2010     void PushbackIsString(bool isString) override
2011     {
2012         infoIsString.push_back(isString);
2013     }
2014 
GetInfoIsStringSize()2015     size_t GetInfoIsStringSize() const
2016     {
2017         return infoIsString.size();
2018     }
2019 
GetInfoIsStringElemt(size_t n)2020     bool GetInfoIsStringElemt(size_t n) const override
2021     {
2022         DEBUG_ASSERT(n < infoIsString.size(), "array index out of range");
2023         return infoIsString.at(n);
2024     }
2025 
GetPragmaVec()2026     std::vector<MIRPragma *> &GetPragmaVec() override
2027     {
2028         return pragmaVec;
2029     }
GetPragmaVec()2030     const std::vector<MIRPragma *> &GetPragmaVec() const override
2031     {
2032         return pragmaVec;
2033     }
PushbackPragma(MIRPragma * pragma)2034     void PushbackPragma(MIRPragma *pragma) override
2035     {
2036         pragmaVec.push_back(pragma);
2037     }
2038 
GetStaticValue()2039     const MIREncodedArray &GetStaticValue() const override
2040     {
2041         return staticValue;
2042     }
PushbackStaticValue(EncodedValue & encodedValue)2043     void PushbackStaticValue(EncodedValue &encodedValue) override
2044     {
2045         staticValue.push_back(encodedValue);
2046     }
2047 
GetParentTyIdx()2048     TyIdx GetParentTyIdx() const
2049     {
2050         return parentTyIdx;
2051     }
SetParentTyIdx(TyIdx idx)2052     void SetParentTyIdx(TyIdx idx)
2053     {
2054         parentTyIdx = idx;
2055     }
2056 
GetInterfaceImplemented()2057     std::vector<TyIdx> &GetInterfaceImplemented()
2058     {
2059         return interfacesImplemented;
2060     }
GetInterfaceImplemented()2061     const std::vector<TyIdx> &GetInterfaceImplemented() const
2062     {
2063         return interfacesImplemented;
2064     }
GetNthInterfaceImplemented(size_t i)2065     TyIdx GetNthInterfaceImplemented(size_t i) const
2066     {
2067         DEBUG_ASSERT(i < interfacesImplemented.size(), "array index out of range");
2068         return interfacesImplemented.at(i);
2069     }
2070 
SetNthInterfaceImplemented(size_t i,TyIdx tyIdx)2071     void SetNthInterfaceImplemented(size_t i, TyIdx tyIdx)
2072     {
2073         DEBUG_ASSERT(i < interfacesImplemented.size(), "array index out of range");
2074         interfacesImplemented.at(i) = tyIdx;
2075     }
PushbackInterfaceImplemented(TyIdx idx)2076     void PushbackInterfaceImplemented(TyIdx idx)
2077     {
2078         interfacesImplemented.push_back(idx);
2079     }
2080 
2081     void Dump(int indent, bool dontUseName = false) const override;
2082     void DumpAsCxx(int indent) const override;
SetComplete()2083     void SetComplete() override
2084     {
2085         typeKind = kTypeClass;
2086     }
2087 
2088     bool IsFinal() const;
2089     bool IsAbstract() const;
2090     bool IsInner() const;
2091     bool HasVolatileField() const override;
2092     bool HasTypeParam() const override;
2093     FieldPair TraverseToFieldRef(FieldID &fieldID) const override;
2094     size_t GetSize() const override;
2095 
2096     FieldID GetLastFieldID() const;
GetFirstFieldID()2097     FieldID GetFirstFieldID() const
2098     {
2099         return GetLastFieldID() - fields.size() + 1;
2100     }
2101 
2102     FieldID GetFirstLocalFieldID() const;
2103     // return class id or superclass id accroding to input string
AddImplementedInterface(TyIdx interfaceTyIdx)2104     void AddImplementedInterface(TyIdx interfaceTyIdx)
2105     {
2106         if (std::find(interfacesImplemented.begin(), interfacesImplemented.end(), interfaceTyIdx) ==
2107             interfacesImplemented.end()) {
2108             interfacesImplemented.push_back(interfaceTyIdx);
2109         }
2110     }
2111 
ClearContents()2112     void ClearContents() override
2113     {
2114         MIRStructType::ClearContents();
2115         parentTyIdx = TyIdx(0);
2116         interfacesImplemented.clear();  // for the list of interfaces the class implements
2117         info.clear();
2118         infoIsString.clear();
2119         pragmaVec.clear();
2120         staticValue.clear();
2121     }
2122 
GetHashIndex()2123     size_t GetHashIndex() const override
2124     {
2125         return ((static_cast<size_t>(nameStrIdx) << kShiftNumOfNameStrIdx) + (typeKind << kShiftNumOfTypeKind)) %
2126                kTypeHashLength;
2127     }
2128 
2129     uint32 NumberOfFieldIDs() const override;
2130 
2131 private:
2132     TyIdx parentTyIdx {0};
2133     std::vector<TyIdx> interfacesImplemented {};  // for the list of interfaces the class implements
2134     std::vector<MIRInfoPair> info {};
2135     std::vector<bool> infoIsString {};
2136     std::vector<MIRPragma *> pragmaVec {};
2137     MIREncodedArray staticValue {};  // DELETE THIS
2138 };
2139 
2140 // used by kTypeInterface, kTypeInterfaceIncomplete
2141 class MIRInterfaceType : public MIRStructType {
2142 public:
MIRInterfaceType(MIRTypeKind tKind)2143     explicit MIRInterfaceType(MIRTypeKind tKind) : MIRStructType(tKind) {}
MIRInterfaceType(MIRTypeKind tKind,GStrIdx strIdx)2144     MIRInterfaceType(MIRTypeKind tKind, GStrIdx strIdx) : MIRStructType(tKind, strIdx) {}
2145     ~MIRInterfaceType() override = default;
2146 
2147     bool EqualTo(const MIRType &type) const override;
2148 
CopyMIRTypeNode()2149     MIRType *CopyMIRTypeNode() const override
2150     {
2151         return new MIRInterfaceType(*this);
2152     }
2153 
GetInfo()2154     const std::vector<MIRInfoPair> &GetInfo() const override
2155     {
2156         return info;
2157     }
PushbackMIRInfo(const MIRInfoPair & pair)2158     void PushbackMIRInfo(const MIRInfoPair &pair) override
2159     {
2160         info.push_back(pair);
2161     }
2162     uint32 GetInfo(const std::string &infoStr) const;
2163     uint32 GetInfo(GStrIdx strIdx) const;
GetInfoSize()2164     size_t GetInfoSize() const
2165     {
2166         return info.size();
2167     }
2168 
GetInfoElemt(size_t n)2169     const MIRInfoPair &GetInfoElemt(size_t n) const override
2170     {
2171         DEBUG_ASSERT(n < info.size(), "array index out of range");
2172         return info.at(n);
2173     }
2174 
GetInfoIsString()2175     const std::vector<bool> &GetInfoIsString() const override
2176     {
2177         return infoIsString;
2178     }
PushbackIsString(bool isString)2179     void PushbackIsString(bool isString) override
2180     {
2181         infoIsString.push_back(isString);
2182     }
GetInfoIsStringSize()2183     size_t GetInfoIsStringSize() const
2184     {
2185         return infoIsString.size();
2186     }
GetInfoIsStringElemt(size_t n)2187     bool GetInfoIsStringElemt(size_t n) const override
2188     {
2189         DEBUG_ASSERT(n < infoIsString.size(), "array index out of range");
2190         return infoIsString.at(n);
2191     }
2192 
GetPragmaVec()2193     std::vector<MIRPragma *> &GetPragmaVec() override
2194     {
2195         return pragmaVec;
2196     }
GetPragmaVec()2197     const std::vector<MIRPragma *> &GetPragmaVec() const override
2198     {
2199         return pragmaVec;
2200     }
PushbackPragma(MIRPragma * pragma)2201     void PushbackPragma(MIRPragma *pragma) override
2202     {
2203         pragmaVec.push_back(pragma);
2204     }
2205 
GetStaticValue()2206     const MIREncodedArray &GetStaticValue() const override
2207     {
2208         return staticValue;
2209     }
PushbackStaticValue(EncodedValue & encodedValue)2210     void PushbackStaticValue(EncodedValue &encodedValue) override
2211     {
2212         staticValue.push_back(encodedValue);
2213     }
2214 
GetParentsTyIdx()2215     std::vector<TyIdx> &GetParentsTyIdx()
2216     {
2217         return parentsTyIdx;
2218     }
SetParentsTyIdx(const std::vector<TyIdx> & parents)2219     void SetParentsTyIdx(const std::vector<TyIdx> &parents)
2220     {
2221         parentsTyIdx = parents;
2222     }
GetParentsTyIdx()2223     const std::vector<TyIdx> &GetParentsTyIdx() const
2224     {
2225         return parentsTyIdx;
2226     }
2227 
GetParentsElementTyIdx(size_t i)2228     TyIdx GetParentsElementTyIdx(size_t i) const
2229     {
2230         DEBUG_ASSERT(i < parentsTyIdx.size(), "array index out of range");
2231         return parentsTyIdx[i];
2232     }
2233 
SetParentsElementTyIdx(size_t i,TyIdx tyIdx)2234     void SetParentsElementTyIdx(size_t i, TyIdx tyIdx)
2235     {
2236         DEBUG_ASSERT(i < parentsTyIdx.size(), "array index out of range");
2237         parentsTyIdx[i] = tyIdx;
2238     }
2239 
2240     void Dump(int indent, bool dontUseName = false) const override;
2241     bool HasVolatileField() const override;
2242     bool HasTypeParam() const override;
2243     FieldPair TraverseToFieldRef(FieldID &fieldID) const override;
SetComplete()2244     void SetComplete() override
2245     {
2246         typeKind = kTypeInterface;
2247     }
2248 
2249     size_t GetSize() const override;
2250 
ClearContents()2251     void ClearContents() override
2252     {
2253         MIRStructType::ClearContents();
2254         parentsTyIdx.clear();
2255         info.clear();
2256         infoIsString.clear();
2257         pragmaVec.clear();
2258         staticValue.clear();
2259     }
2260 
GetHashIndex()2261     size_t GetHashIndex() const override
2262     {
2263         return ((static_cast<size_t>(nameStrIdx) << kShiftNumOfNameStrIdx) + (typeKind << kShiftNumOfTypeKind)) %
2264                kTypeHashLength;
2265     }
2266 
HasFields()2267     bool HasFields() const override
2268     {
2269         return false;
2270     }
NumberOfFieldIDs()2271     uint32 NumberOfFieldIDs() const override
2272     {
2273         return 0;
2274     }
EmbeddedStructType()2275     MIRStructType *EmbeddedStructType() override
2276     {
2277         return nullptr;
2278     }
2279 
2280 private:
2281     std::vector<TyIdx> parentsTyIdx {};  // multiple inheritence
2282     std::vector<MIRInfoPair> info {};
2283     std::vector<bool> infoIsString {};
2284     std::vector<MIRPragma *> pragmaVec {};
2285     MIREncodedArray staticValue {};  // DELETE THIS
2286 };
2287 
2288 class MIRBitFieldType : public MIRType {
2289 public:
MIRBitFieldType(uint8 field,PrimType pt)2290     MIRBitFieldType(uint8 field, PrimType pt) : MIRType(kTypeBitField, pt), fieldSize(field) {}
MIRBitFieldType(uint8 field,PrimType pt,GStrIdx strIdx)2291     MIRBitFieldType(uint8 field, PrimType pt, GStrIdx strIdx) : MIRType(kTypeBitField, pt, strIdx), fieldSize(field) {}
2292     ~MIRBitFieldType() override = default;
2293 
GetFieldSize()2294     uint8 GetFieldSize() const
2295     {
2296         return fieldSize;
2297     }
2298 
2299     bool EqualTo(const MIRType &type) const override;
2300     void Dump(int indent, bool dontUseName = false) const override;
CopyMIRTypeNode()2301     MIRType *CopyMIRTypeNode() const override
2302     {
2303         return new MIRBitFieldType(*this);
2304     }
2305 
GetSize()2306     size_t GetSize() const override
2307     {
2308         if (fieldSize == 0) {
2309             return 0;
2310         } else if (fieldSize <= k8ByteSize) {
2311             return 1;
2312         } else {
2313             return (fieldSize + k7ByteSize) / k8ByteSize;
2314         }
2315     }  // size not be in bytes
2316 
GetAlign()2317     uint32 GetAlign() const override
2318     {
2319         return 0;
2320     }  // align not be in bytes
2321 
GetHashIndex()2322     size_t GetHashIndex() const override
2323     {
2324         return ((static_cast<uint32>(primType) << fieldSize) + (typeKind << kShiftNumOfTypeKind)) % kTypeHashLength;
2325     }
2326 
2327 private:
2328     uint8 fieldSize;
2329 };
2330 
2331 class MIRFuncType : public MIRType {
2332 public:
MIRFuncType()2333     MIRFuncType() : MIRType(kTypeFunction, PTY_ptr) {}
2334 
MIRFuncType(const GStrIdx & strIdx)2335     explicit MIRFuncType(const GStrIdx &strIdx) : MIRType(kTypeFunction, PTY_ptr, strIdx) {}
2336 
MIRFuncType(const TyIdx & retTyIdx,const std::vector<TyIdx> & vecTy,const std::vector<TypeAttrs> & vecAt,const TypeAttrs & retAttrsIn)2337     MIRFuncType(const TyIdx &retTyIdx, const std::vector<TyIdx> &vecTy, const std::vector<TypeAttrs> &vecAt,
2338                 const TypeAttrs &retAttrsIn)
2339         : MIRType(kTypeFunction, PTY_ptr),
2340           retTyIdx(retTyIdx),
2341           paramTypeList(vecTy),
2342           paramAttrsList(vecAt),
2343           retAttrs(retAttrsIn)
2344     {
2345     }
2346 
2347     ~MIRFuncType() override = default;
2348 
2349     bool EqualTo(const MIRType &type) const override;
2350     bool CompatibleWith(const MIRType &type) const;
CopyMIRTypeNode()2351     MIRType *CopyMIRTypeNode() const override
2352     {
2353         return new MIRFuncType(*this);
2354     }
2355 
2356     void Dump(int indent, bool dontUseName = false) const override;
GetSize()2357     size_t GetSize() const override
2358     {
2359         return 0;
2360     }  // size unknown
2361 
GetRetTyIdx()2362     TyIdx GetRetTyIdx() const
2363     {
2364         return retTyIdx;
2365     }
2366 
SetRetTyIdx(TyIdx idx)2367     void SetRetTyIdx(TyIdx idx)
2368     {
2369         retTyIdx = idx;
2370     }
2371 
GetParamTypeList()2372     const std::vector<TyIdx> &GetParamTypeList() const
2373     {
2374         return paramTypeList;
2375     }
2376 
GetParamTypeList()2377     std::vector<TyIdx> &GetParamTypeList()
2378     {
2379         return paramTypeList;
2380     }
2381 
GetNthParamType(size_t i)2382     TyIdx GetNthParamType(size_t i) const
2383     {
2384         DEBUG_ASSERT(i < paramTypeList.size(), "array index out of range");
2385         return paramTypeList[i];
2386     }
2387 
SetParamTypeList(const std::vector<TyIdx> & list)2388     void SetParamTypeList(const std::vector<TyIdx> &list)
2389     {
2390         paramTypeList.clear();
2391         (void)paramTypeList.insert(paramTypeList.begin(), list.begin(), list.end());
2392     }
2393 
GetParamAttrsList()2394     const std::vector<TypeAttrs> &GetParamAttrsList() const
2395     {
2396         return paramAttrsList;
2397     }
2398 
GetParamAttrsList()2399     std::vector<TypeAttrs> &GetParamAttrsList()
2400     {
2401         return paramAttrsList;
2402     }
2403 
GetNthParamAttrs(size_t i)2404     const TypeAttrs &GetNthParamAttrs(size_t i) const
2405     {
2406         DEBUG_ASSERT(i < paramAttrsList.size(), "array index out of range");
2407         return paramAttrsList[i];
2408     }
2409 
GetNthParamAttrs(size_t i)2410     TypeAttrs &GetNthParamAttrs(size_t i)
2411     {
2412         DEBUG_ASSERT(i < paramAttrsList.size(), "array index out of range");
2413         return paramAttrsList[i];
2414     }
2415 
SetParamAttrsList(const std::vector<TypeAttrs> & list)2416     void SetParamAttrsList(const std::vector<TypeAttrs> &list)
2417     {
2418         paramAttrsList.clear();
2419         (void)paramAttrsList.insert(paramAttrsList.begin(), list.begin(), list.end());
2420     }
2421 
SetNthParamAttrs(size_t i,const TypeAttrs & attrs)2422     void SetNthParamAttrs(size_t i, const TypeAttrs &attrs)
2423     {
2424         DEBUG_ASSERT(i < paramAttrsList.size(), "array index out of range");
2425         paramAttrsList[i] = attrs;
2426     }
2427 
IsVarargs()2428     bool IsVarargs() const
2429     {
2430         return funcAttrs.GetAttr(FUNCATTR_varargs);
2431     }
2432 
SetVarArgs()2433     void SetVarArgs()
2434     {
2435         funcAttrs.SetAttr(FUNCATTR_varargs);
2436     }
2437 
FirstArgReturn()2438     bool FirstArgReturn() const
2439     {
2440         return funcAttrs.GetAttr(FUNCATTR_firstarg_return);
2441     }
2442 
SetFirstArgReturn()2443     void SetFirstArgReturn()
2444     {
2445         funcAttrs.SetAttr(FUNCATTR_firstarg_return);
2446     }
2447 
GetRetAttrs()2448     const TypeAttrs &GetRetAttrs() const
2449     {
2450         return retAttrs;
2451     }
2452 
GetRetAttrs()2453     TypeAttrs &GetRetAttrs()
2454     {
2455         return retAttrs;
2456     }
2457 
SetRetAttrs(const TypeAttrs & attrs)2458     void SetRetAttrs(const TypeAttrs &attrs)
2459     {
2460         retAttrs = attrs;
2461     }
2462 
GetHashIndex()2463     size_t GetHashIndex() const override
2464     {
2465         constexpr uint8 idxShift = 6;
2466         size_t hIdx = (static_cast<size_t>(retTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
2467         size_t size = paramTypeList.size();
2468         hIdx += (size ? (static_cast<size_t>(paramTypeList[0]) + size) : 0) << 4;  // shift bit is 4
2469         return hIdx % kTypeHashLength;
2470     }
2471 
2472 public:
2473     FuncAttrs funcAttrs;
2474 
2475 private:
2476     TyIdx retTyIdx {0};
2477     std::vector<TyIdx> paramTypeList;
2478     std::vector<TypeAttrs> paramAttrsList;
2479     TypeAttrs retAttrs;
2480 };
2481 
2482 class MIRTypeByName : public MIRType {
2483     // use nameStrIdx to store the name for both local and global
2484 public:
MIRTypeByName(GStrIdx gStrIdx)2485     explicit MIRTypeByName(GStrIdx gStrIdx) : MIRType(kTypeByName, PTY_void)
2486     {
2487         nameStrIdx = gStrIdx;
2488     }
2489 
2490     ~MIRTypeByName() override = default;
2491 
CopyMIRTypeNode()2492     MIRType *CopyMIRTypeNode() const override
2493     {
2494         return new MIRTypeByName(*this);
2495     }
2496 
2497     bool EqualTo(const MIRType &type) const override;
2498 
2499     void Dump(int indent, bool dontUseName = false) const override;
GetSize()2500     size_t GetSize() const override
2501     {
2502         return 0;
2503     }  // size unknown
2504 
GetHashIndex()2505     size_t GetHashIndex() const override
2506     {
2507         constexpr uint8 idxShift = 2;
2508         return ((static_cast<size_t>(nameStrIdx) << idxShift) + nameIsLocal + (typeKind << kShiftNumOfTypeKind)) %
2509                kTypeHashLength;
2510     }
2511 };
2512 
2513 class MIRTypeParam : public MIRType {
2514     // use nameStrIdx to store the name
2515 public:
MIRTypeParam(GStrIdx gStrIdx)2516     explicit MIRTypeParam(GStrIdx gStrIdx) : MIRType(kTypeParam, PTY_gen)
2517     {
2518         nameStrIdx = gStrIdx;
2519     }
2520 
2521     ~MIRTypeParam() override = default;
2522 
CopyMIRTypeNode()2523     MIRType *CopyMIRTypeNode() const override
2524     {
2525         return new MIRTypeParam(*this);
2526     }
2527 
2528     bool EqualTo(const MIRType &type) const override;
2529     void Dump(int indent, bool dontUseName = false) const override;
GetSize()2530     size_t GetSize() const override
2531     {
2532         return 0;
2533     }  // size unknown
2534 
HasTypeParam()2535     bool HasTypeParam() const override
2536     {
2537         return true;
2538     }
2539 
GetHashIndex()2540     size_t GetHashIndex() const override
2541     {
2542         constexpr uint8 idxShift = 3;
2543         return ((static_cast<size_t>(nameStrIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind)) % kTypeHashLength;
2544     }
2545 };
2546 
2547 using TypePair = std::pair<TyIdx, TyIdx>;
2548 using GenericInstantVector = std::vector<TypePair>;
2549 class MIRInstantVectorType : public MIRType {
2550 public:
MIRInstantVectorType()2551     MIRInstantVectorType() : MIRType(kTypeInstantVector, PTY_agg) {}
2552 
MIRInstantVectorType(MIRTypeKind kind)2553     explicit MIRInstantVectorType(MIRTypeKind kind) : MIRType(kind, PTY_agg) {}
2554 
MIRInstantVectorType(MIRTypeKind kind,GStrIdx strIdx)2555     MIRInstantVectorType(MIRTypeKind kind, GStrIdx strIdx) : MIRType(kind, PTY_agg, strIdx) {}
2556 
2557     ~MIRInstantVectorType() override = default;
2558 
CopyMIRTypeNode()2559     MIRType *CopyMIRTypeNode() const override
2560     {
2561         return new MIRInstantVectorType(*this);
2562     }
2563 
2564     bool EqualTo(const MIRType &type) const override;
2565     void Dump(int indent, bool dontUseName = false) const override;
GetSize()2566     size_t GetSize() const override
2567     {
2568         return 0;
2569     }  // size unknown
2570 
GetInstantVec()2571     const GenericInstantVector &GetInstantVec() const
2572     {
2573         return instantVec;
2574     }
2575 
GetInstantVec()2576     GenericInstantVector &GetInstantVec()
2577     {
2578         return instantVec;
2579     }
2580 
AddInstant(TypePair typePair)2581     void AddInstant(TypePair typePair)
2582     {
2583         instantVec.push_back(typePair);
2584     }
2585 
GetHashIndex()2586     size_t GetHashIndex() const override
2587     {
2588         constexpr uint8 idxShift = 3;
2589         uint32 hIdx = typeKind << kShiftNumOfTypeKind;
2590         for (const TypePair &typePair : instantVec) {
2591             hIdx += static_cast<uint32>(typePair.first + typePair.second) << idxShift;
2592         }
2593         return hIdx % kTypeHashLength;
2594     }
2595 
2596 protected:
2597     GenericInstantVector instantVec {};  // in each pair, first is generic type, second is real type
2598 };
2599 
2600 class MIRGenericInstantType : public MIRInstantVectorType {
2601 public:
MIRGenericInstantType(TyIdx genTyIdx)2602     explicit MIRGenericInstantType(TyIdx genTyIdx) : MIRInstantVectorType(kTypeGenericInstant), genericTyIdx(genTyIdx)
2603     {
2604     }
2605 
MIRGenericInstantType(GStrIdx strIdx)2606     explicit MIRGenericInstantType(GStrIdx strIdx) : MIRInstantVectorType(kTypeGenericInstant, strIdx), genericTyIdx(0)
2607     {
2608     }
2609 
2610     ~MIRGenericInstantType() override = default;
2611 
CopyMIRTypeNode()2612     MIRType *CopyMIRTypeNode() const override
2613     {
2614         return new MIRGenericInstantType(*this);
2615     }
2616 
2617     bool EqualTo(const MIRType &type) const override;
2618     void Dump(int indent, bool dontUseName = false) const override;
2619 
GetSize()2620     size_t GetSize() const override
2621     {
2622         return 0;
2623     }  // size unknown
2624 
GetGenericTyIdx()2625     TyIdx GetGenericTyIdx() const
2626     {
2627         return genericTyIdx;
2628     }
SetGenericTyIdx(TyIdx idx)2629     void SetGenericTyIdx(TyIdx idx)
2630     {
2631         genericTyIdx = idx;
2632     }
2633 
GetHashIndex()2634     size_t GetHashIndex() const override
2635     {
2636         constexpr uint8 idxShift = 2;
2637         uint32 hIdx = (static_cast<uint32>(genericTyIdx) << idxShift) + (typeKind << kShiftNumOfTypeKind);
2638         for (const TypePair &typePair : instantVec) {
2639             hIdx += static_cast<uint32>(typePair.first + typePair.second) << k8BitShift;  // shift bit is 3
2640         }
2641         return hIdx % kTypeHashLength;
2642     }
2643 
2644 private:
2645     TyIdx genericTyIdx;  // the generic type to be instantiated
2646 };
2647 
2648 MIRType *GetElemType(const MIRType &arrayType);
2649 // aarch64 specific
2650 bool IsHomogeneousAggregates(const MIRType &ty, PrimType &primType, size_t &elemNum, bool firstDepth = true);
2651 bool IsParamStructCopyToMemory(const MIRType &ty);
2652 bool IsReturnInMemory(const MIRType &ty);
2653 #endif  // MIR_FEATURE_FULL
2654 }  // namespace maple
2655 
2656 #define LOAD_SAFE_CAST_FOR_MIR_TYPE
2657 #include "ir_safe_cast_traits.def"
2658 
2659 #endif  // MAPLE_IR_INCLUDE_MIR_TYPE_H
2660