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