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