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