• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mir_type.h"
17 #include "mir_symbol.h"
18 #include "printing.h"
19 #include "namemangler.h"
20 #include "global_tables.h"
21 #include "mir_builder.h"
22 #include "cfg_primitive_types.h"
23 #include "string_utils.h"
24 #include "triple.h"
25 #if MIR_FEATURE_FULL
26 
27 namespace maple {
28 #define LOAD_PRIMARY_TYPE_PROPERTY
29 #include "prim_types.def"
30 
31 #define LOAD_ALGO_PRIMARY_TYPE
GetPrimitiveTypeProperty(PrimType pType)32 const PrimitiveTypeProperty &GetPrimitiveTypeProperty(PrimType pType)
33 {
34     switch (pType) {
35         case PTY_begin:
36             return PTProperty_begin;
37 #define PRIMTYPE(P) \
38     case PTY_##P:   \
39         return PTProperty_##P;
40 #include "prim_types.def"
41 #undef PRIMTYPE
42         case PTY_end:
43         default:
44             return PTProperty_end;
45     }
46 }
47 
GetRegPrimType(PrimType primType)48 PrimType GetRegPrimType(PrimType primType)
49 {
50     switch (primType) {
51         case PTY_i8:
52         case PTY_i16:
53             return PTY_i32;
54         case PTY_u1:
55         case PTY_u8:
56         case PTY_u16:
57             return PTY_u32;
58         default:
59             return primType;
60     }
61 }
62 
GetReg64PrimType(PrimType primType)63 PrimType GetReg64PrimType(PrimType primType)
64 {
65     switch (primType) {
66         case PTY_i8:
67         case PTY_i16:
68         case PTY_i32:
69             return PTY_i64;
70         case PTY_u1:
71         case PTY_u8:
72         case PTY_u16:
73         case PTY_u32:
74             return PTY_u64;
75         default:
76             return primType;
77     }
78 }
79 
VerifyPrimType(PrimType primType1,PrimType primType2)80 bool VerifyPrimType(PrimType primType1, PrimType primType2)
81 {
82     switch (primType1) {
83         case PTY_u1:
84         case PTY_u8:
85         case PTY_u16:
86         case PTY_u32:
87         case PTY_a32:
88             return IsUnsignedInteger(primType2);
89         case PTY_i8:
90         case PTY_i16:
91         case PTY_i32:
92             return IsSignedInteger(primType2);
93         default:
94             return primType1 == primType2;
95     }
96 }
97 
GetDynType(PrimType primType)98 PrimType GetDynType(PrimType primType)
99 {
100 #ifdef DYNAMICLANG
101     switch (primType) {
102         case PTY_u1:
103             return PTY_dynbool;
104         case PTY_i32:
105             return PTY_dyni32;
106         case PTY_simplestr:
107             return PTY_dynstr;
108         case PTY_simpleobj:
109             return PTY_dynobj;
110         case PTY_f32:
111             return PTY_dynf32;
112         case PTY_f64:
113             return PTY_dynf64;
114         default:
115             return primType;
116     }
117 #else
118     return primType;
119 #endif
120 }
121 
GetNonDynType(PrimType primType)122 PrimType GetNonDynType(PrimType primType)
123 {
124 #ifdef DYNAMICLANG
125     switch (primType) {
126         case PTY_dynbool:
127             return PTY_u1;
128         case PTY_dyni32:
129             return PTY_i32;
130         case PTY_dynstr:
131             return PTY_simplestr;
132         case PTY_dynobj:
133             return PTY_simpleobj;
134         case PTY_dynf32:
135             return PTY_f32;
136         case PTY_dynf64:
137             return PTY_f64;
138         default:
139             return primType;
140     }
141 #else
142     return primType;
143 #endif
144 }
145 
GetIntegerPrimTypeBySizeAndSign(size_t sizeBit,bool isSign)146 PrimType GetIntegerPrimTypeBySizeAndSign(size_t sizeBit, bool isSign)
147 {
148     switch (sizeBit) {
149         case k1BitSize: {
150             if (isSign) {
151                 return PTY_begin;  // There is no 'i1' type
152             }
153             return PTY_u1;
154         }
155         case k8BitSize: {
156             return isSign ? PTY_i8 : PTY_u8;
157         }
158         case k16BitSize: {
159             return isSign ? PTY_i16 : PTY_u16;
160         }
161         case k32BitSize: {
162             return isSign ? PTY_i32 : PTY_u32;
163         }
164         case k64BitSize: {
165             return isSign ? PTY_i64 : PTY_u64;
166         }
167         default: {
168             return PTY_begin;  // Invalid integer type
169         }
170     }
171 }
172 
IsNoCvtNeeded(PrimType toType,PrimType fromType)173 bool IsNoCvtNeeded(PrimType toType, PrimType fromType)
174 {
175     if (toType == fromType) {
176         return true;
177     }
178     switch (toType) {
179         case PTY_i32:
180             return fromType == PTY_i16 || fromType == PTY_i8;
181         case PTY_u32:
182             return fromType == PTY_u16 || fromType == PTY_u8;
183         case PTY_u1:
184         case PTY_u8:
185         case PTY_u16:
186             return fromType == PTY_u32;
187         case PTY_i8:
188         case PTY_i16:
189             return fromType == PTY_i32;
190         case PTY_i64:
191         case PTY_u64:
192         case PTY_a64:
193         case PTY_ptr:
194             return fromType == PTY_ptr || fromType == PTY_u64 || fromType == PTY_a64 || fromType == PTY_i64;
195         default:
196             return false;
197     }
198 }
199 
NeedCvtOrRetype(PrimType origin,PrimType compared)200 bool NeedCvtOrRetype(PrimType origin, PrimType compared)
201 {
202     return GetPrimTypeSize(origin) != GetPrimTypeSize(compared) || IsSignedInteger(origin) != IsSignedInteger(compared);
203 }
204 
GetPointerSize()205 uint8 GetPointerSize()
206 {
207 #if TARGX86 || TARGARM32 || TARGVM
208     return k4ByteSize;
209 #elif TARGX86_64
210     return k8ByteSize;
211 #elif TARGAARCH64
212     DEBUG_ASSERT(Triple::GetTriple().GetEnvironment() != Triple::UnknownEnvironment,
213                  "Triple must be initialized before using");
214     uint8 size = (Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) ? k4ByteSize : k8ByteSize;
215     return size;
216 #else
217 #error "Unsupported target"
218 #endif
219 }
220 
GetP2Size()221 uint8 GetP2Size()
222 {
223 #if TARGX86 || TARGARM32 || TARGVM
224     return k2ByteSize;
225 #elif TARGX86_64
226     return k3ByteSize;
227 #elif TARGAARCH64
228     DEBUG_ASSERT(Triple::GetTriple().GetEnvironment() != Triple::UnknownEnvironment,
229                  "Triple must be initialized before using");
230     uint8 size = (Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) ? k2ByteSize : k3ByteSize;
231     return size;
232 #else
233 #error "Unsupported target"
234 #endif
235 }
236 
GetLoweredPtrType()237 PrimType GetLoweredPtrType()
238 {
239 #if TARGX86 || TARGARM32 || TARGVM
240     return PTY_a32;
241 #elif TARGX86_64
242     return PTY_a64;
243 #elif TARGAARCH64
244     DEBUG_ASSERT(Triple::GetTriple().GetEnvironment() != Triple::UnknownEnvironment,
245                  "Triple must be initialized before using");
246     auto pty = (Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) ? PTY_a32 : PTY_a64;
247     return pty;
248 #else
249 #error "Unsupported target"
250 #endif
251 }
252 
GetExactPtrPrimType()253 PrimType GetExactPtrPrimType()
254 {
255     return (GetPointerSize() == k8ByteSize) ? PTY_a64 : PTY_a32;
256 }
257 
258 // answer in bytes; 0 if unknown
GetPrimTypeSize(PrimType primType)259 uint32 GetPrimTypeSize(PrimType primType)
260 {
261     switch (primType) {
262         case PTY_void:
263         case PTY_agg:
264             return k0BitSize;
265         case PTY_ptr:
266         case PTY_ref:
267             return GetPointerSize();
268         case PTY_u1:
269         case PTY_i8:
270         case PTY_u8:
271             return k1BitSize;
272         case PTY_i16:
273         case PTY_u16:
274             return k2BitSize;
275         case PTY_a32:
276         case PTY_f32:
277         case PTY_i32:
278         case PTY_u32:
279         case PTY_simplestr:
280         case PTY_simpleobj:
281             return k4BitSize;
282         case PTY_a64:
283         case PTY_c64:
284         case PTY_f64:
285         case PTY_i64:
286         case PTY_u64:
287         case PTY_v2i32:
288         case PTY_v4i16:
289         case PTY_v8i8:
290         case PTY_v2u32:
291         case PTY_v4u16:
292         case PTY_v8u8:
293         case PTY_v2f32:
294             return k8BitSize;
295         case PTY_u128:
296         case PTY_i128:
297         case PTY_c128:
298         case PTY_f128:
299         case PTY_v2i64:
300         case PTY_v4i32:
301         case PTY_v8i16:
302         case PTY_v16i8:
303         case PTY_v2u64:
304         case PTY_v4u32:
305         case PTY_v8u16:
306         case PTY_v16u8:
307         case PTY_v2f64:
308         case PTY_v4f32:
309             return k16BitSize;
310 #ifdef DYNAMICLANG
311         case PTY_dynf32:
312         case PTY_dyni32:
313         case PTY_dynstr:
314         case PTY_dynobj:
315         case PTY_dynundef:
316         case PTY_dynnull:
317         case PTY_dynbool:
318             return k8BitSize;
319         case PTY_dynany:
320         case PTY_dynf64:
321             return k8BitSize;
322 #endif
323         default:
324             return k0BitSize;
325     }
326 }
327 
328 // answer is n if size in byte is (1<<n) (0: 1B; 1: 2B, 2: 4B, 3: 8B, 4:16B)
GetPrimTypeP2Size(PrimType primType)329 uint32 GetPrimTypeP2Size(PrimType primType)
330 {
331     switch (primType) {
332         case PTY_ptr:
333         case PTY_ref:
334             return GetP2Size();
335         case PTY_u1:
336         case PTY_i8:
337         case PTY_u8:
338             return k0BitSize;
339         case PTY_i16:
340         case PTY_u16:
341             return k1BitSize;
342         case PTY_a32:
343         case PTY_f32:
344         case PTY_i32:
345         case PTY_u32:
346         case PTY_simplestr:
347         case PTY_simpleobj:
348             return k2BitSize;
349         case PTY_a64:
350         case PTY_c64:
351         case PTY_f64:
352         case PTY_i64:
353         case PTY_u64:
354         case PTY_v2i32:
355         case PTY_v4i16:
356         case PTY_v8i8:
357         case PTY_v2u32:
358         case PTY_v4u16:
359         case PTY_v8u8:
360         case PTY_v2f32:
361             return k3BitSize;
362         case PTY_c128:
363         case PTY_f128:
364         case PTY_v2i64:
365         case PTY_v4i32:
366         case PTY_v8i16:
367         case PTY_v16i8:
368         case PTY_v2u64:
369         case PTY_v4u32:
370         case PTY_v8u16:
371         case PTY_v16u8:
372         case PTY_v2f64:
373         case PTY_v4f32:
374             return k4BitSize;
375 #ifdef DYNAMICLANG
376         case PTY_dynf32:
377         case PTY_dyni32:
378         case PTY_dynstr:
379         case PTY_dynobj:
380         case PTY_dynundef:
381         case PTY_dynnull:
382         case PTY_dynbool:
383         case PTY_dynany:
384         case PTY_dynf64:
385             return k3BitSize;
386 #endif
387         default:
388             DEBUG_ASSERT(false, "Power-of-2 size only applicable to sizes of 1, 2, 4, 8 or 16 bytes.");
389             return k10BitSize;
390     }
391 }
392 
GetVecEleSize(PrimType primType)393 uint32 GetVecEleSize(PrimType primType)
394 {
395     switch (primType) {
396         case PTY_v2i64:
397         case PTY_v2u64:
398         case PTY_v2f64:
399         case PTY_i64:
400         case PTY_u64:
401         case PTY_f64:
402             return k64BitSize;
403         case PTY_v2i32:
404         case PTY_v2u32:
405         case PTY_v2f32:
406         case PTY_v4i32:
407         case PTY_v4u32:
408         case PTY_v4f32:
409             return k32BitSize;
410         case PTY_v4i16:
411         case PTY_v4u16:
412         case PTY_v8i16:
413         case PTY_v8u16:
414             return k16BitSize;
415         case PTY_v8i8:
416         case PTY_v8u8:
417         case PTY_v16i8:
418         case PTY_v16u8:
419             return k8BitSize;
420         default:
421             CHECK_FATAL(false, "unexpected primtType for vector");
422     }
423 }
424 
GetVecLanes(PrimType primType)425 uint32 GetVecLanes(PrimType primType)
426 {
427     switch (primType) {
428         case PTY_v2i32:
429         case PTY_v2u32:
430         case PTY_v2f32:
431         case PTY_v2i64:
432         case PTY_v2u64:
433         case PTY_v2f64:
434             return k2BitSize;
435         case PTY_v4i16:
436         case PTY_v4u16:
437         case PTY_v4i32:
438         case PTY_v4u32:
439         case PTY_v4f32:
440             return k4BitSize;
441         case PTY_v8i8:
442         case PTY_v8u8:
443         case PTY_v8i16:
444         case PTY_v8u16:
445             return k8BitSize;
446         case PTY_v16i8:
447         case PTY_v16u8:
448             return k16BitSize;
449         default:
450             return 0;
451     }
452 }
453 
GetVecElemPrimType(PrimType primType)454 PrimType GetVecElemPrimType(PrimType primType)
455 {
456     switch (primType) {
457         case PTY_v2i32:
458         case PTY_v4i32:
459             return PTY_i32;
460         case PTY_v2u32:
461         case PTY_v4u32:
462             return PTY_u32;
463         case PTY_v2i64:
464             return PTY_i64;
465         case PTY_v2u64:
466             return PTY_u64;
467         case PTY_v16i8:
468         case PTY_v8i8:
469             return PTY_i8;
470         case PTY_v16u8:
471         case PTY_v8u8:
472             return PTY_u8;
473         case PTY_v8i16:
474         case PTY_v4i16:
475             return PTY_i16;
476         case PTY_v8u16:
477         case PTY_v4u16:
478             return PTY_u16;
479         case PTY_v2f32:
480         case PTY_v4f32:
481             return PTY_f32;
482         case PTY_v2f64:
483             return PTY_f64;
484         default:
485             return PTY_begin;  // not a vector type
486     }
487     return PTY_begin;  // not a vector type
488 }
489 
490 // return the signed version that has the same size
GetSignedPrimType(PrimType pty)491 PrimType GetSignedPrimType(PrimType pty)
492 {
493     switch (pty) {
494         case PTY_ptr:
495         case PTY_ref:
496         case PTY_a64:
497         case PTY_u64:
498             return PTY_i64;
499         case PTY_u8:
500             return PTY_i8;
501         case PTY_u16:
502             return PTY_i16;
503         case PTY_a32:
504         case PTY_u32:
505             return PTY_i32;
506         default:;
507     }
508     return pty;
509 }
510 
511 // return the unsigned version that has the same size
GetUnsignedPrimType(PrimType pty)512 PrimType GetUnsignedPrimType(PrimType pty)
513 {
514     switch (pty) {
515         case PTY_i64:
516             return PTY_u64;
517         case PTY_i8:
518             return PTY_u8;
519         case PTY_i16:
520             return PTY_u16;
521         case PTY_i32:
522             return PTY_u32;
523         default:;
524     }
525     return pty;
526 }
527 
MinValOfSignedInteger(PrimType primType)528 int64 MinValOfSignedInteger(PrimType primType)
529 {
530     switch (primType) {
531         case PTY_i8:
532             return INT8_MIN;
533         case PTY_i16:
534             return INT16_MIN;
535         case PTY_i32:
536             return INT32_MIN;
537         case PTY_i64:
538             return INT64_MIN;
539         default:
540             CHECK_FATAL(false, "NIY");
541             return 0;
542     }
543 }
544 
GetPrimTypeName(PrimType primType)545 const char *GetPrimTypeName(PrimType primType)
546 {
547 #define LOAD_ALGO_PRIMARY_TYPE
548     switch (primType) {
549         case kPtyInvalid:
550             return "kPtyInvalid";
551 #define PRIMTYPE(P) \
552     case PTY_##P:   \
553         return #P;
554 #include "prim_types.def"
555 #undef PRIMTYPE
556         case kPtyDerived:
557             return "derived";  // just for test: no primitive type for derived
558         default:
559             return "kPtyInvalid";
560     }
561     // SIMD types to be defined
562 }
563 
GetPrimTypeJavaName(PrimType primType)564 const char *GetPrimTypeJavaName(PrimType primType)
565 {
566     switch (primType) {
567         case PTY_u1:
568             return "Z";
569         case PTY_i8:
570             return "B";
571         case PTY_i16:
572             return "S";
573         case PTY_u16:
574             return "C";
575         case PTY_i32:
576             return "I";
577         case PTY_i64:
578             return "J";
579         case PTY_f32:
580             return "F";
581         case PTY_f64:
582             return "D";
583         case PTY_void:
584             return "V";
585         case PTY_constStr:
586             return kJstrTypeName.c_str();
587         case kPtyInvalid:
588             return "invalid";
589         default:
590             return "invalid";
591     }
592 }
593 
DumpAttributes() const594 void StmtAttrs::DumpAttributes() const
595 {
596 #define STMT_ATTR
597 #define STRING(s) #s
598 #define ATTR(AT)                \
599     if (GetAttr(STMTATTR_##AT)) \
600         LogInfo::MapleLogger() << STRING(AT);
601 #include "all_attributes.def"
602 #undef ATTR
603 #undef STMT_ATTR
604 }
605 
DumpAttributes() const606 void TypeAttrs::DumpAttributes() const
607 {
608 // dump attr without content
609 #define TYPE_ATTR
610 #define NOCONTENT_ATTR
611 #define STRING(s) #s
612 #define ATTR(AT)            \
613     if (GetAttr(ATTR_##AT)) \
614         LogInfo::MapleLogger() << " " << STRING(AT);
615 #include "all_attributes.def"
616 #undef ATTR
617 #undef NOCONTENT_ATTR
618 #undef TYPE_ATTR
619     // dump attr with content
620     if (attrAlign) {
621         LogInfo::MapleLogger() << " align(" << GetAlign() << ")";
622     }
623     if (GetAttr(ATTR_pack) && GetPack() != 0) {
624         LogInfo::MapleLogger() << " pack(" << GetPack() << ")";
625     }
626 }
627 
DumpAttributes() const628 void FieldAttrs::DumpAttributes() const
629 {
630 // dump attr without content
631 #define FIELD_ATTR
632 #define NOCONTENT_ATTR
633 #define STRING(s) #s
634 #define ATTR(AT)               \
635     if (GetAttr(FLDATTR_##AT)) \
636         LogInfo::MapleLogger() << " " << STRING(AT);
637 #include "all_attributes.def"
638 #undef ATTR
639 #undef NOCONTENT_ATTR
640 #undef FIELD_ATTR
641     // dump attr with content
642     if (attrAlign) {
643         LogInfo::MapleLogger() << " align(" << GetAlign() << ")";
644     }
645     if (IsPacked()) {
646         LogInfo::MapleLogger() << " pack(1)";
647     }
648 }
649 
GetName() const650 const std::string &MIRType::GetName() const
651 {
652     return GlobalTables::GetStrTable().GetStringFromStrIdx(nameStrIdx);
653 }
654 
ValidateClassOrInterface(const std::string & className,bool noWarning) const655 bool MIRType::ValidateClassOrInterface(const std::string &className, bool noWarning) const
656 {
657     if (primType == maple::PTY_agg && (typeKind == maple::kTypeClass || typeKind == maple::kTypeInterface) &&
658         nameStrIdx != 0u) {
659         return true;
660     }
661     if (!noWarning) {
662         size_t len = className.size();
663         constexpr int minClassNameLen = 4;
664         constexpr char suffix[] = "_3B";
665         size_t suffixLen = std::strlen(suffix);
666         if (len > minClassNameLen && strncmp(className.c_str() + len - suffixLen, suffix, suffixLen) == 0) {
667             LogInfo::MapleLogger(kLlErr) << "error: missing proper mplt file for " << className << '\n';
668         } else {
669             LogInfo::MapleLogger(kLlErr) << "internal error: type is not java class or interface " << className << '\n';
670         }
671     }
672     return false;
673 }
674 
PointsToConstString() const675 bool MIRType::PointsToConstString() const
676 {
677     return (typeKind == kTypePointer) ? static_cast<const MIRPtrType *>(this)->PointsToConstString() : false;
678 }
679 
GetMplTypeName() const680 std::string MIRType::GetMplTypeName() const
681 {
682     if (typeKind == kTypeScalar) {
683         return GetPrimTypeName(primType);
684     }
685     return "";
686 }
687 
GetCompactMplTypeName() const688 std::string MIRType::GetCompactMplTypeName() const
689 {
690     if (typeKind == kTypeScalar) {
691         return GetPrimTypeJavaName(primType);
692     }
693     return "";
694 }
695 
Dump(int indent,bool dontUseName) const696 void MIRType::Dump(int indent, bool dontUseName) const
697 {
698     LogInfo::MapleLogger() << GetPrimTypeName(primType);
699 }
700 
DumpAsCxx(int indent) const701 void MIRType::DumpAsCxx(int indent) const
702 {
703     switch (primType) {
704         case PTY_void:
705             LogInfo::MapleLogger() << "void";
706             break;
707         case PTY_i8:
708             LogInfo::MapleLogger() << "int8 ";
709             break;
710         case PTY_i16:
711             LogInfo::MapleLogger() << "int16";
712             break;
713         case PTY_i32:
714             LogInfo::MapleLogger() << "int32";
715             break;
716         case PTY_i64:
717             LogInfo::MapleLogger() << "int64";
718             break;
719         case PTY_u8:
720             LogInfo::MapleLogger() << "uint8";
721             break;
722         case PTY_u16:
723             LogInfo::MapleLogger() << "uint16";
724             break;
725         case PTY_u32:
726             LogInfo::MapleLogger() << "uint32";
727             break;
728         case PTY_u64:
729             LogInfo::MapleLogger() << "uint64";
730             break;
731         case PTY_u1:
732             LogInfo::MapleLogger() << "bool  ";
733             break;
734         case PTY_ptr:
735             LogInfo::MapleLogger() << "void* ";
736             break;
737         case PTY_ref:
738             LogInfo::MapleLogger() << "void* ";
739             break;
740         case PTY_a32:
741             LogInfo::MapleLogger() << "int32";
742             break;
743         case PTY_a64:
744             LogInfo::MapleLogger() << "void* ";
745             break;
746         case PTY_f32:
747             LogInfo::MapleLogger() << "float ";
748             break;
749         case PTY_f64:
750             LogInfo::MapleLogger() << "double";
751             break;
752         case PTY_c64:
753             LogInfo::MapleLogger() << "float complex";
754             break;
755         case PTY_c128:
756             LogInfo::MapleLogger() << "double complex";
757             break;
758         default:
759             DEBUG_ASSERT(false, "not yet implemented");
760     }
761 }
762 
IsOfSameType(MIRType & type)763 bool MIRType::IsOfSameType(MIRType &type)
764 {
765     if (typeKind != type.typeKind) {
766         return false;
767     }
768 
769     if (typeKind == kTypePointer) {
770         const auto &ptrType = static_cast<const MIRPtrType &>(*this);
771         const auto &ptrTypeIt = static_cast<const MIRPtrType &>(type);
772         if (ptrType.GetPointedTyIdx() == ptrTypeIt.GetPointedTyIdx()) {
773             return true;
774         } else {
775             MIRType &mirTypeIt = *GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrTypeIt.GetPointedTyIdx());
776             return GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrType.GetPointedTyIdx())->IsOfSameType(mirTypeIt);
777         }
778     } else if (typeKind == kTypeJArray) {
779         auto &arrType1 = static_cast<MIRJarrayType &>(*this);
780         auto &arrType2 = static_cast<MIRJarrayType &>(type);
781         if (arrType1.GetDim() != arrType2.GetDim()) {
782             return false;
783         }
784         return arrType1.GetElemType()->IsOfSameType(*arrType2.GetElemType());
785     } else {
786         return tyIdx == type.tyIdx;
787     }
788 }
789 
DumpTypeName(GStrIdx strIdx,bool isLocal)790 inline void DumpTypeName(GStrIdx strIdx, bool isLocal)
791 {
792     LogInfo::MapleLogger() << ((isLocal) ? "%" : "$") << GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx);
793 }
794 
CheckAndDumpTypeName(GStrIdx strIdx,bool isLocal)795 static bool CheckAndDumpTypeName(GStrIdx strIdx, bool isLocal)
796 {
797     if (strIdx == 0u) {
798         return false;
799     }
800     LogInfo::MapleLogger() << "<";
801     DumpTypeName(strIdx, isLocal);
802     LogInfo::MapleLogger() << ">";
803     return true;
804 }
805 
Dump(int indent,bool dontUseName) const806 void MIRFuncType::Dump(int indent, bool dontUseName) const
807 {
808     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
809         return;
810     }
811     LogInfo::MapleLogger() << "<func";
812     funcAttrs.DumpAttributes();
813     LogInfo::MapleLogger() << " (";
814     size_t size = paramTypeList.size();
815     for (size_t i = 0; i < size; ++i) {
816         GlobalTables::GetTypeTable().GetTypeFromTyIdx(paramTypeList[i])->Dump(indent + 1);
817         if (i < paramAttrsList.size()) {
818             paramAttrsList[i].DumpAttributes();
819         }
820         if (size - 1 != i) {
821             LogInfo::MapleLogger() << ",";
822         }
823     }
824     if (IsVarargs()) {
825         LogInfo::MapleLogger() << ", ...";
826     }
827     LogInfo::MapleLogger() << ") ";
828     GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx)->Dump(indent + 1);
829     retAttrs.DumpAttributes();
830     LogInfo::MapleLogger() << ">";
831 }
832 
RoundUpConst(uint64 offset,uint32 align)833 static constexpr uint64 RoundUpConst(uint64 offset, uint32 align)
834 {
835     uint64 tempFirst = static_cast<uint64>(-align);
836     uint64 tempSecond = static_cast<uint64>(offset + align - 1);
837     return tempFirst & tempSecond;
838 }
839 
RoundUp(uint64 offset,uint32 align)840 static inline uint64 RoundUp(uint64 offset, uint32 align)
841 {
842     if (align == 0) {
843         return offset;
844     }
845     return RoundUpConst(offset, align);
846 }
847 
RoundDownConst(uint64 offset,uint32 align)848 static constexpr uint64 RoundDownConst(uint64 offset, uint32 align)
849 {
850     uint64 temp = static_cast<uint64>(-align);
851     return temp & offset;
852 }
853 
RoundDown(uint64 offset,uint32 align)854 static inline uint64 RoundDown(uint64 offset, uint32 align)
855 {
856     if (align == 0) {
857         return offset;
858     }
859     return RoundDownConst(offset, align);
860 }
861 
GetSize() const862 size_t MIRArrayType::GetSize() const
863 {
864     if (size != kInvalidSize) {
865         return size;
866     }
867     size_t elemsize = GetElemType()->GetSize();
868     if (elemsize == 0) {
869         return 0;
870     }
871     elemsize = RoundUp(elemsize, typeAttrs.GetAlign());
872     size_t numelems = sizeArray[0];
873     for (uint16 i = 1; i < dim; i++) {
874         numelems *= sizeArray[i];
875     }
876     size = elemsize * numelems;
877     return size;
878 }
879 
GetAlign() const880 uint32 MIRArrayType::GetAlign() const
881 {
882     if (GetSize() == 0) {
883         return typeAttrs.GetAlign();
884     }
885     return std::max(GetElemType()->GetAlign(), typeAttrs.GetAlign());
886 }
887 
Dump(int indent,bool dontUseName) const888 void MIRArrayType::Dump(int indent, bool dontUseName) const
889 {
890     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
891         return;
892     }
893     LogInfo::MapleLogger() << "<";
894     for (uint16 i = 0; i < dim; ++i) {
895         LogInfo::MapleLogger() << "[" << GetSizeArrayItem(i) << "]";
896     }
897     LogInfo::MapleLogger() << " ";
898     GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx)->Dump(indent + 1);
899     GetTypeAttrs().DumpAttributes();
900     LogInfo::MapleLogger() << ">";
901 }
902 
GetCompactMplTypeName() const903 std::string MIRArrayType::GetCompactMplTypeName() const
904 {
905     std::stringstream ss;
906     ss << "A";
907     MIRType *elemType = GetElemType();
908     ss << elemType->GetCompactMplTypeName();
909     return ss.str();
910 }
911 
Dump(int indent,bool dontUseName) const912 void MIRFarrayType::Dump(int indent, bool dontUseName) const
913 {
914     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
915         return;
916     }
917     LogInfo::MapleLogger() << "<[] ";
918     GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx)->Dump(indent + 1);
919     LogInfo::MapleLogger() << ">";
920 }
921 
GetCompactMplTypeName() const922 std::string MIRFarrayType::GetCompactMplTypeName() const
923 {
924     std::stringstream ss;
925     ss << "A";
926     MIRType *elemType = GetElemType();
927     ss << elemType->GetCompactMplTypeName();
928     return ss.str();
929 }
930 
GetJavaName()931 const std::string &MIRJarrayType::GetJavaName()
932 {
933     if (javaNameStrIdx == 0u) {
934         DetermineName();
935     }
936     return GlobalTables::GetStrTable().GetStringFromStrIdx(javaNameStrIdx);
937 }
938 
GetParentType()939 MIRStructType *MIRJarrayType::GetParentType()
940 {
941     if (parentTyIdx == 0u) {
942         GStrIdx jloStrIdx = GlobalTables::GetStrTable().GetStrIdxFromName(
943             namemangler::GetInternalNameLiteral(namemangler::kJavaLangObjectStr));
944         parentTyIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(jloStrIdx);
945         DEBUG_ASSERT((parentTyIdx != 0u), "cannot find type for java.lang.Object");
946     }
947     return static_cast<MIRStructType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx));
948 }
949 
DetermineName()950 void MIRJarrayType::DetermineName()
951 {
952     if (javaNameStrIdx != 0u) {
953         return;  // already determined
954     }
955     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetElemTyIdx());
956     dim = 1;
957     std::string baseName;
958     while (true) {
959         if (elemType->GetKind() == kTypeScalar) {
960             baseName = GetPrimTypeJavaName(elemType->GetPrimType());
961             fromPrimitive = true;
962             break;
963         } else if (elemType->GetKind() == kTypePointer) {
964             auto *pType = static_cast<MIRPtrType *>(elemType)->GetPointedType();
965             DEBUG_ASSERT(pType != nullptr, "pType is null in MIRJarrayType::DetermineName");
966             if (pType->GetKind() == kTypeByName || pType->GetKind() == kTypeClass ||
967                 pType->GetKind() == kTypeInterface || pType->GetKind() == kTypeClassIncomplete ||
968                 pType->GetKind() == kTypeInterfaceIncomplete) {
969                 baseName = static_cast<MIRStructType *>(pType)->GetName();
970                 fromPrimitive = false;
971                 break;
972             } else if (pType->GetKind() == kTypeJArray) {
973                 auto *tmpPtype = static_cast<MIRJarrayType *>(pType);
974                 elemType = tmpPtype->GetElemType();
975                 DEBUG_ASSERT(elemType != nullptr, "elemType is null in MIRJarrayType::DetermineName");
976                 ++dim;
977             } else {
978                 DEBUG_ASSERT(false, "unexpected type!");
979             }
980         } else {
981             DEBUG_ASSERT(false, "unexpected type!");
982         }
983     }
984     std::string name;
985     for (int i = dim; i > 0; --i) {
986         name += JARRAY_PREFIX_STR;
987     }
988     name += baseName;
989     javaNameStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name);
990 }
991 
GetPointedType() const992 MIRType *MIRPtrType::GetPointedType() const
993 {
994     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
995 }
996 
IsVolatile(int fieldID) const997 bool MIRType::IsVolatile(int fieldID) const
998 {
999     if (fieldID == 0) {
1000         return HasVolatileField();
1001     }
1002     return static_cast<const MIRStructType *>(this)->IsFieldVolatile(fieldID);
1003 }
1004 
HasTypeParam() const1005 bool MIRPtrType::HasTypeParam() const
1006 {
1007     return GetPointedType()->HasTypeParam();
1008 }
1009 
PointsToConstString() const1010 bool MIRPtrType::PointsToConstString() const
1011 {
1012     GStrIdx typeNameIdx = GetPointedType()->GetNameStrIdx();
1013     std::string typeName = GlobalTables::GetStrTable().GetStringFromStrIdx(typeNameIdx);
1014     return typeName == "Ljava_2Flang_2FString_3B";
1015 }
1016 
Dump(int indent,bool dontUseName) const1017 void MIRPtrType::Dump(int indent, bool dontUseName) const
1018 {
1019     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
1020         return;
1021     }
1022     MIRType *pointedType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
1023     if (pointedType->GetKind() == kTypeFunction) {  // no * for function pointer
1024         pointedType->Dump(indent);
1025     } else {
1026         LogInfo::MapleLogger() << "<* ";
1027         pointedType->Dump(indent + 1);
1028         typeAttrs.DumpAttributes();
1029         LogInfo::MapleLogger() << ">";
1030     }
1031 }
1032 
Dump(int indent,bool dontUseName) const1033 void MIRBitFieldType::Dump(int indent, bool dontUseName) const
1034 {
1035     LogInfo::MapleLogger() << ":" << static_cast<int>(fieldSize) << " " << GetPrimTypeName(primType);
1036 }
1037 
GetSize() const1038 size_t MIRClassType::GetSize() const
1039 {
1040     if (parentTyIdx == 0u) {
1041         return MIRStructType::GetSize();
1042     }
1043     if (size != kInvalidSize) {
1044         return size;
1045     }
1046     const auto *parentType =
1047         static_cast<const MIRClassType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx));
1048     size_t parentSize = parentType->GetSize();
1049     if (parentSize == 0) {
1050         return 0;
1051     }
1052     size_t structSize = MIRStructType::GetSize();
1053     if (structSize == 0) {
1054         return 0;
1055     }
1056     size = parentSize + structSize;
1057     return size;
1058 }
1059 
GetFirstLocalFieldID() const1060 FieldID MIRClassType::GetFirstLocalFieldID() const
1061 {
1062     if (!IsLocal()) {
1063         return 0;
1064     }
1065     if (parentTyIdx == 0u) {
1066         return 1;
1067     }
1068 
1069     constexpr uint8 lastFieldIDOffset = 2;
1070     constexpr uint8 firstLocalFieldIDOffset = 1;
1071     const auto *parentClassType =
1072         static_cast<const MIRClassType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx));
1073     return !parentClassType->IsLocal() ? parentClassType->GetLastFieldID() + lastFieldIDOffset
1074                                        : parentClassType->GetFirstLocalFieldID() + firstLocalFieldIDOffset;
1075 }
1076 
GetExceptionRootType() const1077 const MIRClassType *MIRClassType::GetExceptionRootType() const
1078 {
1079     GStrIdx ehTypeNameIdx = GlobalTables::GetStrTable().GetStrIdxFromName(namemangler::kJavaLangObjectStr);
1080     const MIRClassType *subClassType = this;
1081     while (subClassType != nullptr && subClassType->nameStrIdx != ehTypeNameIdx) {
1082         subClassType =
1083             static_cast<const MIRClassType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(subClassType->parentTyIdx));
1084     }
1085     return subClassType;
1086 }
1087 
GetExceptionRootType()1088 MIRClassType *MIRClassType::GetExceptionRootType()
1089 {
1090     return const_cast<MIRClassType *>(const_cast<const MIRClassType *>(this)->GetExceptionRootType());
1091 }
1092 
IsExceptionType() const1093 bool MIRClassType::IsExceptionType() const
1094 {
1095     GStrIdx ehTypeNameIdx = GlobalTables::GetStrTable().GetStrIdxFromName("Ljava_2Flang_2FThrowable_3B");
1096     const MIRClassType *parentClassType = this;
1097     while (parentClassType != nullptr && parentClassType->nameStrIdx != ehTypeNameIdx) {
1098         parentClassType =
1099             static_cast<MIRClassType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentClassType->parentTyIdx));
1100     }
1101     return parentClassType != nullptr;
1102 }
1103 
GetLastFieldID() const1104 FieldID MIRClassType::GetLastFieldID() const
1105 {
1106     FieldID fieldID = fields.size();
1107     if (parentTyIdx != 0u) {
1108         const auto *parentClassType =
1109             static_cast<const MIRClassType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx));
1110         if (parentClassType != nullptr) {
1111             fieldID += parentClassType->GetLastFieldID() + 1;
1112         }
1113     }
1114     return fieldID;
1115 }
1116 
DumpClassOrInterfaceInfo(const MIRStructType & type,int indent)1117 static void DumpClassOrInterfaceInfo(const MIRStructType &type, int indent)
1118 {
1119     const std::vector<MIRInfoPair> &info = type.GetInfo();
1120     std::vector<bool> infoIsString = type.GetInfoIsString();
1121     size_t size = info.size();
1122     for (size_t i = 0; i < size; ++i) {
1123         LogInfo::MapleLogger() << '\n';
1124         PrintIndentation(indent);
1125         LogInfo::MapleLogger() << "@" << GlobalTables::GetStrTable().GetStringFromStrIdx(info[i].first) << " ";
1126         if (!infoIsString[i]) {
1127             LogInfo::MapleLogger() << info[i].second;
1128         } else {
1129             LogInfo::MapleLogger() << "\"" << GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(info[i].second))
1130                                    << "\"";
1131         }
1132         if (i != size - 1) {
1133             LogInfo::MapleLogger() << ",";
1134         }
1135     }
1136 }
1137 
GetInfoFromStrIdx(const std::vector<MIRInfoPair> & info,const GStrIdx & strIdx)1138 static uint32 GetInfoFromStrIdx(const std::vector<MIRInfoPair> &info, const GStrIdx &strIdx)
1139 {
1140     for (MIRInfoPair infoPair : info) {
1141         if (infoPair.first == strIdx) {
1142             return infoPair.second;
1143         }
1144     }
1145     return 0;
1146 }
1147 
GetInfo(GStrIdx strIdx) const1148 uint32 MIRInterfaceType::GetInfo(GStrIdx strIdx) const
1149 {
1150     return GetInfoFromStrIdx(info, strIdx);
1151 }
1152 
1153 // return class id or superclass id accroding to input string
GetInfo(const std::string & infoStr) const1154 uint32 MIRInterfaceType::GetInfo(const std::string &infoStr) const
1155 {
1156     GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(infoStr);
1157     return GetInfo(strIdx);
1158 }
GetSize() const1159 size_t MIRInterfaceType::GetSize() const
1160 {
1161     if (size != kInvalidSize) {
1162         return size;
1163     }
1164     size = MIRStructType::GetSize();
1165     if (parentsTyIdx.empty()) {
1166         return size;
1167     }
1168     if (size == 0) {
1169         return 0;
1170     }
1171     for (size_t i = 0; i < parentsTyIdx.size(); ++i) {
1172         const auto *parentType =
1173             static_cast<const MIRInterfaceType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentsTyIdx[i]));
1174         size_t parentSize = parentType->GetSize();
1175         if (parentSize == 0) {
1176             return 0;
1177         }
1178         size += parentSize;
1179     }
1180     return size;
1181 }
1182 
DumpStaticValue(const MIREncodedArray & staticValue,int indent)1183 static void DumpStaticValue(const MIREncodedArray &staticValue, int indent)
1184 {
1185     if (staticValue.empty()) {
1186         return;
1187     }
1188     LogInfo::MapleLogger() << '\n';
1189     PrintIndentation(indent);
1190     LogInfo::MapleLogger() << "@staticvalue";
1191     constexpr uint32 typeLen = 5;
1192     constexpr uint32 typeMask = 0x1f;
1193     for (const auto &value : staticValue) {
1194         LogInfo::MapleLogger() << " [";
1195         uint8 valueArg = static_cast<uint32>(value.encodedValue[0]) >> typeLen;
1196         uint8 valueType = static_cast<uint32>(value.encodedValue[0]) & typeMask;
1197         // kValueNull kValueBoolean
1198         constexpr uint32 simpleOffset = 1;
1199         constexpr uint32 aggOffSet = 2;
1200         valueArg = (valueType == kValueNull || valueType == kValueBoolean) ? simpleOffset : valueArg + aggOffSet;
1201         for (uint32 k = 0; k < valueArg; ++k) {
1202             LogInfo::MapleLogger() << static_cast<uint32>(value.encodedValue[k]);
1203             if (k != static_cast<uint32>(valueArg - 1)) {
1204                 LogInfo::MapleLogger() << " ";
1205             }
1206         }
1207         LogInfo::MapleLogger() << "]";
1208     }
1209 }
1210 
DumpFields(FieldVector fields,int indent,bool otherFields=false)1211 static void DumpFields(FieldVector fields, int indent, bool otherFields = false)
1212 {
1213     size_t size = fields.size();
1214     for (size_t i = 0; i < size; ++i) {
1215         LogInfo::MapleLogger() << '\n';
1216         PrintIndentation(indent);
1217         LogInfo::MapleLogger() << ((!otherFields) ? "@" : "^")
1218                                << GlobalTables::GetStrTable().GetStringFromStrIdx(fields[i].first) << " ";
1219         GlobalTables::GetTypeTable().GetTypeFromTyIdx(fields[i].second.first)->Dump(indent + 1);
1220         FieldAttrs &fa = fields[i].second.second;
1221         fa.DumpAttributes();
1222         if (fa.GetAttr(FLDATTR_static) && fa.GetAttr(FLDATTR_final) &&
1223             (fa.GetAttr(FLDATTR_public) || fa.GetAttr(FLDATTR_protected))) {
1224             const char *fieldName = GlobalTables::GetStrTable().GetStringFromStrIdx(fields[i].first).c_str();
1225             MIRSymbol *fieldVar = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
1226                 GlobalTables::GetStrTable().GetStrIdxFromName(fieldName));
1227             if (fieldVar != nullptr && fieldVar->GetKonst() != nullptr &&
1228                 fieldVar->GetKonst()->GetKind() == kConstStr16Const) {
1229                 LogInfo::MapleLogger() << " = ";
1230                 fieldVar->GetKonst()->Dump();
1231             }
1232         }
1233         if (i != size - 1) {
1234             LogInfo::MapleLogger() << ",";
1235         }
1236     }
1237 }
1238 
DumpFieldsAsCxx(const FieldVector & fields,int indent)1239 static void DumpFieldsAsCxx(const FieldVector &fields, int indent)
1240 {
1241     for (auto &f : fields) {
1242         PrintIndentation(indent);
1243         const FieldAttrs &fa = f.second.second;
1244         if (fa.GetAttr(FLDATTR_static)) {
1245             LogInfo::MapleLogger() << "// ";
1246         }
1247         LogInfo::MapleLogger() << "/* ";
1248         fa.DumpAttributes();
1249         GlobalTables::GetTypeTable().GetTypeFromTyIdx(f.second.first)->Dump(indent + 1);
1250         LogInfo::MapleLogger() << " */ ";
1251         GlobalTables::GetTypeTable().GetTypeFromTyIdx(f.second.first)->DumpAsCxx(indent + 1);
1252         LogInfo::MapleLogger() << " " << GlobalTables::GetStrTable().GetStringFromStrIdx(f.first) << ";" << '\n';
1253     }
1254 }
1255 
DumpMethods(MethodVector methods,int indent)1256 static void DumpMethods(MethodVector methods, int indent)
1257 {
1258     size_t size = methods.size();
1259     for (size_t i = 0; i < size; ++i) {
1260         LogInfo::MapleLogger() << '\n';
1261         PrintIndentation(indent);
1262         MIRSymbol *mFirstSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(methods[i].first.Idx());
1263         DEBUG_ASSERT(mFirstSymbol != nullptr, "null ptr check");
1264         LogInfo::MapleLogger() << "&" << mFirstSymbol->GetName();
1265         methods[i].second.second.DumpAttributes();
1266         LogInfo::MapleLogger() << " (";
1267         auto *funcType =
1268             static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(methods[i].second.first));
1269         size_t parmListSize = funcType->GetParamTypeList().size();
1270         for (size_t j = 0; j < parmListSize; ++j) {
1271             GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetNthParamType(j))->Dump(indent + 1);
1272             if (j != parmListSize - 1) {
1273                 LogInfo::MapleLogger() << ",";
1274             }
1275         }
1276         if (funcType->IsVarargs()) {
1277             LogInfo::MapleLogger() << ", ...";
1278         }
1279         LogInfo::MapleLogger() << ") ";
1280         GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx())->Dump(indent + 1);
1281         if (i != size - 1) {
1282             LogInfo::MapleLogger() << ",";
1283         }
1284     }
1285 }
1286 
DumpConstructorsAsCxx(MethodVector methods,int indent)1287 static void DumpConstructorsAsCxx(MethodVector methods, int indent)
1288 {
1289     unsigned int i = 0;
1290     for (auto &m : methods) {
1291         FuncAttrs &fa = m.second.second;
1292         if (!fa.GetAttr(FUNCATTR_constructor) || !fa.GetAttr(FUNCATTR_public)) {
1293             continue;
1294         }
1295         auto *funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(m.second.first));
1296         PrintIndentation(indent);
1297         MIRSymbol *mFirstSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(m.first.Idx());
1298         DEBUG_ASSERT(mFirstSymbol != nullptr, "null ptr check");
1299         LogInfo::MapleLogger() << "/* &" << mFirstSymbol->GetName();
1300         fa.DumpAttributes();
1301         LogInfo::MapleLogger() << " (";
1302         unsigned int j = 0;
1303         size_t paramTypeListSize = funcType->GetParamTypeList().size();
1304         for (auto &p : funcType->GetParamTypeList()) {
1305             GlobalTables::GetTypeTable().GetTypeFromTyIdx(p)->Dump(indent + 1);
1306             if (j != paramTypeListSize - 1) {
1307                 LogInfo::MapleLogger() << ", ";
1308             }
1309             ++j;
1310         }
1311         if (funcType->IsVarargs()) {
1312             LogInfo::MapleLogger() << ", ...";
1313         }
1314         LogInfo::MapleLogger() << ") ";
1315         GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx())->Dump(indent + 1);
1316         LogInfo::MapleLogger() << " */" << '\n';
1317         PrintIndentation(indent);
1318         LogInfo::MapleLogger() << "/* ";
1319         LogInfo::MapleLogger() << namemangler::DecodeName(mFirstSymbol->GetName());
1320         LogInfo::MapleLogger() << " */" << '\n';
1321         PrintIndentation(indent);
1322         LogInfo::MapleLogger() << "extern \"C\" ";
1323         // return type
1324         GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx())->DumpAsCxx(0);
1325         LogInfo::MapleLogger() << " " << mFirstSymbol->GetName() << "( ";
1326         j = 0;
1327         for (auto &p : funcType->GetParamTypeList()) {
1328             GlobalTables::GetTypeTable().GetTypeFromTyIdx(p)->DumpAsCxx(indent + 1);
1329             if (j != paramTypeListSize - 1) {
1330                 LogInfo::MapleLogger() << ", ";
1331             }
1332             ++j;
1333         }
1334         if (funcType->IsVarargs()) {
1335             LogInfo::MapleLogger() << ", ...";
1336         }
1337         LogInfo::MapleLogger() << ")";
1338         if (methods.size() - 1 != i++) {
1339             LogInfo::MapleLogger() << ";" << '\n';
1340         }
1341     }
1342 }
1343 
DumpInterfaces(std::vector<TyIdx> interfaces,int indent)1344 static void DumpInterfaces(std::vector<TyIdx> interfaces, int indent)
1345 {
1346     size_t size = interfaces.size();
1347     for (size_t i = 0; i < size; ++i) {
1348         LogInfo::MapleLogger() << '\n';
1349         PrintIndentation(indent);
1350         GStrIdx stridx = GlobalTables::GetTypeTable().GetTypeFromTyIdx(interfaces[i])->GetNameStrIdx();
1351         LogInfo::MapleLogger() << "$" << GlobalTables::GetStrTable().GetStringFromStrIdx(stridx);
1352         if (i != size - 1) {
1353             LogInfo::MapleLogger() << ",";
1354         }
1355     }
1356 }
1357 
GetSize() const1358 size_t MIRStructType::GetSize() const
1359 {
1360     if (size != kInvalidSize) {
1361         return size;
1362     }
1363     if (typeKind == kTypeUnion) {
1364         if (fields.size() == 0) {
1365             return isCPlusPlus ? 1 : 0;
1366         }
1367         size = 0;
1368         for (size_t i = 0; i < fields.size(); ++i) {
1369             TyIdxFieldAttrPair tfap = GetTyidxFieldAttrPair(i);
1370             MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first);
1371             size_t fldSize = RoundUp(fieldType->GetSize(), tfap.second.GetAlign());
1372             if (size < fldSize) {
1373                 size = fldSize;
1374             }
1375         }
1376         return size;
1377     }
1378     // since there may be bitfields, perform a layout process for the fields
1379     size_t byteOfst = 0;
1380     size_t bitOfst = 0;
1381     constexpr uint32 shiftNum = 3;
1382     for (size_t i = 0; i < fields.size(); ++i) {
1383         TyIdxFieldAttrPair tfap = GetTyidxFieldAttrPair(i);
1384         MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first);
1385         if (fieldType->GetKind() != kTypeBitField) {
1386             if (byteOfst * k8BitSize < bitOfst) {
1387                 byteOfst = (bitOfst >> shiftNum) + 1;
1388             }
1389             byteOfst = RoundUp(byteOfst, std::max(fieldType->GetAlign(), tfap.second.GetAlign()));
1390             byteOfst += fieldType->GetSize();
1391             bitOfst = byteOfst * k8BitSize;
1392         } else {
1393             MIRBitFieldType *bitfType = static_cast<MIRBitFieldType *>(fieldType);
1394             if (bitfType->GetFieldSize() == 0) {  // special case, for aligning purpose
1395                 bitOfst = RoundUp(bitOfst, GetPrimTypeBitSize(bitfType->GetPrimType()));
1396                 byteOfst = bitOfst >> shiftNum;
1397             } else {
1398                 if (RoundDown(bitOfst + bitfType->GetFieldSize() - 1, GetPrimTypeBitSize(bitfType->GetPrimType())) !=
1399                     RoundDown(bitOfst, GetPrimTypeBitSize(bitfType->GetPrimType()))) {
1400                     bitOfst = RoundUp(bitOfst, GetPrimTypeBitSize(bitfType->GetPrimType()));
1401                     byteOfst = bitOfst >> shiftNum;
1402                 }
1403                 bitOfst += bitfType->GetFieldSize();
1404                 byteOfst = bitOfst >> shiftNum;
1405             }
1406         }
1407     }
1408     if ((byteOfst << k8BitShift) < bitOfst) {
1409         byteOfst = (bitOfst >> shiftNum) + 1;
1410     }
1411     byteOfst = RoundUp(byteOfst, GetAlign());
1412     if (byteOfst == 0 && isCPlusPlus) {
1413         size = 1;
1414         return 1;  // empty struct in C++ has size 1
1415     }
1416     size = byteOfst;
1417     return size;
1418 }
1419 
GetAlign() const1420 uint32 MIRStructType::GetAlign() const
1421 {
1422     if (fields.size() == 0) {
1423         return 0;
1424     }
1425     uint32 maxAlign = 1;
1426     for (size_t i = 0; i < fields.size(); ++i) {
1427         TyIdxFieldAttrPair tfap = GetTyidxFieldAttrPair(i);
1428         MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first);
1429         uint32 algn = fieldType->GetAlign();
1430         if (fieldType->GetKind() == kTypeBitField) {
1431             algn = GetPrimTypeSize(fieldType->GetPrimType());
1432         } else {
1433             algn = std::max(algn, tfap.second.GetAlign());
1434         }
1435         if (maxAlign < algn) {
1436             maxAlign = algn;
1437         }
1438     }
1439     return std::min(maxAlign, GetTypeAttrs().GetPack());
1440 }
1441 
DumpFieldsAndMethods(int indent,bool hasMethod) const1442 void MIRStructType::DumpFieldsAndMethods(int indent, bool hasMethod) const
1443 {
1444     DumpFields(fields, indent);
1445     bool hasField = !fields.empty();
1446     bool hasStaticField = !staticFields.empty();
1447     if (hasField && hasStaticField) {
1448         LogInfo::MapleLogger() << ",";
1449     }
1450     DumpFields(staticFields, indent, true);
1451     bool hasFieldOrStaticField = hasField || hasStaticField;
1452     bool hasParentField = !parentFields.empty();
1453     if (hasFieldOrStaticField && hasParentField) {
1454         LogInfo::MapleLogger() << ",";
1455     }
1456     DumpFields(parentFields, indent, true);
1457     if ((hasFieldOrStaticField || hasParentField) && hasMethod) {
1458         LogInfo::MapleLogger() << ",";
1459     }
1460     DumpMethods(methods, indent);
1461 }
1462 
Dump(int indent,bool dontUseName) const1463 void MIRStructType::Dump(int indent, bool dontUseName) const
1464 {
1465     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
1466         return;
1467     }
1468     LogInfo::MapleLogger() << ((typeKind == kTypeStruct) ? "<struct"
1469                                                          : ((typeKind == kTypeUnion) ? "<union" : "<structincomplete"));
1470     typeAttrs.DumpAttributes();
1471     LogInfo::MapleLogger() << " {";
1472     DumpFieldsAndMethods(indent, !methods.empty());
1473     LogInfo::MapleLogger() << "}>";
1474 }
1475 
GetInfo(GStrIdx strIdx) const1476 uint32 MIRClassType::GetInfo(GStrIdx strIdx) const
1477 {
1478     return GetInfoFromStrIdx(info, strIdx);
1479 }
1480 
1481 // return class id or superclass id accroding to input string
GetInfo(const std::string & infoStr) const1482 uint32 MIRClassType::GetInfo(const std::string &infoStr) const
1483 {
1484     GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(infoStr);
1485     return GetInfo(strIdx);
1486 }
1487 
IsFinal() const1488 bool MIRClassType::IsFinal() const
1489 {
1490     if (!IsStructType()) {
1491         return false;
1492     }
1493     uint32 attrStrIdx = GetInfo(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("INFO_attribute_string"));
1494     CHECK(attrStrIdx < GlobalTables::GetStrTable().StringTableSize(), "out of range of vector");
1495     const std::string &kAttrString = GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(attrStrIdx));
1496     return kAttrString.find(" final ") != std::string::npos;
1497 }
1498 
IsAbstract() const1499 bool MIRClassType::IsAbstract() const
1500 {
1501     uint32 attrStrIdx = GetInfo(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("INFO_attribute_string"));
1502     CHECK(attrStrIdx < GlobalTables::GetStrTable().StringTableSize(), "out of range of vector");
1503     const std::string &kAttrString = GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(attrStrIdx));
1504     return kAttrString.find(" abstract ") != std::string::npos;
1505 }
1506 
IsInner() const1507 bool MIRClassType::IsInner() const
1508 {
1509     const std::string &name = GetName();
1510     return name.find("_24") != std::string::npos;
1511 }
1512 
DumpInfoPragmaStaticValue(const std::vector<MIRInfoPair> & info,const std::vector<MIRPragma * > & pragmaVec,const MIREncodedArray & staticValue,int indent,bool hasFieldMethodOrInterface)1513 static void DumpInfoPragmaStaticValue(const std::vector<MIRInfoPair> &info, const std::vector<MIRPragma *> &pragmaVec,
1514                                       const MIREncodedArray &staticValue, int indent, bool hasFieldMethodOrInterface)
1515 {
1516     bool hasPragma = pragmaVec.size();
1517     bool hasStaticValue = staticValue.size();
1518     if (!info.empty() && (hasPragma || hasStaticValue || hasFieldMethodOrInterface)) {
1519         LogInfo::MapleLogger() << ",";
1520     }
1521     size_t size = pragmaVec.size();
1522     for (size_t i = 0; i < size; ++i) {
1523         pragmaVec[i]->Dump(indent);
1524         if (i != size - 1) {
1525             LogInfo::MapleLogger() << ",";
1526         }
1527     }
1528     if (hasPragma && (hasStaticValue || hasFieldMethodOrInterface)) {
1529         LogInfo::MapleLogger() << ",";
1530     }
1531     DumpStaticValue(staticValue, indent);
1532     if (hasStaticValue && hasFieldMethodOrInterface) {
1533         LogInfo::MapleLogger() << ",";
1534     }
1535 }
1536 
Dump(int indent,bool dontUseName) const1537 void MIRClassType::Dump(int indent, bool dontUseName) const
1538 {
1539     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
1540         return;
1541     }
1542     LogInfo::MapleLogger() << ((typeKind == kTypeClass) ? "<class " : "<classincomplete ");
1543     if (parentTyIdx != 0u) {
1544         GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx)->Dump(indent + 1);
1545         LogInfo::MapleLogger() << " ";
1546     }
1547     LogInfo::MapleLogger() << "{";
1548     DumpClassOrInterfaceInfo(*this, indent);
1549     bool hasFieldMethodOrInterface = !(fields.empty() && parentFields.empty() && staticFields.empty() &&
1550                                        methods.empty() && interfacesImplemented.empty());
1551     DumpInfoPragmaStaticValue(info, pragmaVec, staticValue, indent, hasFieldMethodOrInterface);
1552 
1553     bool hasMethod = !methods.empty();
1554     bool hasImplementedInterface = !interfacesImplemented.empty();
1555     DumpFieldsAndMethods(indent, hasMethod || hasImplementedInterface);
1556     if (hasMethod && hasImplementedInterface) {
1557         LogInfo::MapleLogger() << ",";
1558     }
1559     DumpInterfaces(interfacesImplemented, indent);
1560     LogInfo::MapleLogger() << "}>";
1561 }
1562 
DumpAsCxx(int indent) const1563 void MIRClassType::DumpAsCxx(int indent) const
1564 {
1565     LogInfo::MapleLogger() << "{\n";
1566     DumpFieldsAsCxx(fields, indent);
1567     LogInfo::MapleLogger() << "};\n";
1568     DumpConstructorsAsCxx(methods, 0);
1569 }
1570 
Dump(int indent,bool dontUseName) const1571 void MIRInterfaceType::Dump(int indent, bool dontUseName) const
1572 {
1573     if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
1574         return;
1575     }
1576     LogInfo::MapleLogger() << ((typeKind == kTypeInterface) ? "<interface " : "<interfaceincomplete ");
1577     for (TyIdx idx : parentsTyIdx) {
1578         GlobalTables::GetTypeTable().GetTypeFromTyIdx(idx)->Dump(0);
1579         LogInfo::MapleLogger() << " ";
1580     }
1581     LogInfo::MapleLogger() << " {";
1582     DumpClassOrInterfaceInfo(*this, indent);
1583     bool hasFieldOrMethod = !(fields.empty() && staticFields.empty() && parentFields.empty() && methods.empty());
1584     DumpInfoPragmaStaticValue(info, pragmaVec, staticValue, indent, hasFieldOrMethod);
1585     DumpFieldsAndMethods(indent, !methods.empty());
1586     LogInfo::MapleLogger() << "}>";
1587 }
1588 
Dump(int indent,bool dontUseName) const1589 void MIRTypeByName::Dump(int indent, bool dontUseName) const
1590 {
1591     const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(nameStrIdx);
1592     LogInfo::MapleLogger() << (nameIsLocal ? "<%" : "<$") << name << ">";
1593 }
1594 
Dump(int indent,bool dontUseName) const1595 void MIRTypeParam::Dump(int indent, bool dontUseName) const
1596 {
1597     const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(nameStrIdx);
1598     LogInfo::MapleLogger() << "<!" << name << ">";
1599 }
1600 
Dump(int indent,bool dontUseName) const1601 void MIRInstantVectorType::Dump(int indent, bool dontUseName) const
1602 {
1603     LogInfo::MapleLogger() << "{";
1604     for (size_t i = 0; i < instantVec.size(); ++i) {
1605         TypePair typePair = instantVec[i];
1606         if (i != 0) {
1607             LogInfo::MapleLogger() << ", ";
1608         }
1609         MIRType *typeParmType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typePair.first);
1610         const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(typeParmType->GetNameStrIdx());
1611         LogInfo::MapleLogger() << "!" << name << "=";
1612         MIRType *realty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typePair.second);
1613         realty->Dump(0);
1614     }
1615     LogInfo::MapleLogger() << "}";
1616 }
1617 
Dump(int indent,bool dontUseName) const1618 void MIRGenericInstantType::Dump(int indent, bool dontUseName) const
1619 {
1620     LogInfo::MapleLogger() << "<";
1621     const MIRType *genericType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(genericTyIdx);
1622     DumpTypeName(genericType->GetNameStrIdx(), genericType->IsNameIsLocal());
1623     MIRInstantVectorType::Dump(indent, dontUseName);
1624     LogInfo::MapleLogger() << ">";
1625 }
1626 
EqualTo(const MIRType & mirType) const1627 bool MIRType::EqualTo(const MIRType &mirType) const
1628 {
1629     return typeKind == mirType.typeKind && primType == mirType.primType;
1630 }
1631 
EqualTo(const MIRType & type) const1632 bool MIRPtrType::EqualTo(const MIRType &type) const
1633 {
1634     if (typeKind != type.GetKind() || GetPrimType() != type.GetPrimType()) {
1635         return false;
1636     }
1637     const auto &pType = static_cast<const MIRPtrType &>(type);
1638     return pointedTyIdx == pType.GetPointedTyIdx() && typeAttrs == pType.GetTypeAttrs();
1639 }
1640 
EqualTo(const MIRType & type) const1641 bool MIRArrayType::EqualTo(const MIRType &type) const
1642 {
1643     if (type.GetKind() != typeKind) {
1644         return false;
1645     }
1646     const auto &pType = static_cast<const MIRArrayType &>(type);
1647     if (dim != pType.GetDim() || eTyIdx != pType.GetElemTyIdx() || typeAttrs != pType.GetTypeAttrs()) {
1648         return false;
1649     }
1650     for (size_t i = 0; i < dim; ++i) {
1651         if (GetSizeArrayItem(i) != pType.GetSizeArrayItem(i)) {
1652             return false;
1653         }
1654     }
1655     return true;
1656 }
1657 
GetElemType() const1658 MIRType *MIRArrayType::GetElemType() const
1659 {
1660     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx);
1661 }
1662 
GetMplTypeName() const1663 std::string MIRArrayType::GetMplTypeName() const
1664 {
1665     std::stringstream ss;
1666     ss << "<[] ";
1667     MIRType *elemType = GetElemType();
1668     ss << elemType->GetMplTypeName();
1669     ss << ">";
1670     return ss.str();
1671 }
1672 
HasFields() const1673 bool MIRArrayType::HasFields() const
1674 {
1675     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx);
1676     return elemType->HasFields();
1677 }
1678 
NumberOfFieldIDs() const1679 uint32 MIRArrayType::NumberOfFieldIDs() const
1680 {
1681     if (fieldsNum != kInvalidFieldNum) {
1682         return fieldsNum;
1683     }
1684     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx);
1685     fieldsNum = elemType->NumberOfFieldIDs();
1686     return fieldsNum;
1687 }
1688 
EmbeddedStructType()1689 MIRStructType *MIRArrayType::EmbeddedStructType()
1690 {
1691     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx);
1692     return elemType->EmbeddedStructType();
1693 }
1694 
GetBitOffsetFromArrayAddress(std::vector<int64> & indexArray)1695 int64 MIRArrayType::GetBitOffsetFromArrayAddress(std::vector<int64> &indexArray)
1696 {
1697     // for cases that num of dimension-operand is less than array's dimension
1698     // e.g. array 1 ptr <* <[d1][d2][d3] type>> (array_base_addr, dim1_opnd)
1699     // array's dimension is 3, and dimension-opnd's num is 1;
1700     if (indexArray.size() < dim) {
1701         indexArray.insert(indexArray.end(), dim - indexArray.size(), 0);
1702     }
1703     if (GetElemType()->GetKind() == kTypeArray) {
1704         // for cases that array's dimension is less than num of dimension-opnd
1705         // e.g array 1 ptr <* <[d1] <[d2] type>>> (array_base_addr, dim1_opnd, dim2_opnd)
1706         // array's dimension is 1 (its element type is <[d2] type>), and dimension-opnd-num is 2
1707         CHECK_FATAL(indexArray.size() >= dim, "dimension mismatch!");
1708     } else {
1709         CHECK_FATAL(indexArray.size() == dim, "dimension mismatch!");
1710     }
1711     int64 sum = 0;  // element numbers before the specified element
1712     uint32 numberOfElemInLowerDim = 1;
1713     for (uint32 id = 1; id <= dim; ++id) {
1714         sum += indexArray[dim - id] * numberOfElemInLowerDim;
1715         numberOfElemInLowerDim *= sizeArray[dim - id];
1716     }
1717     size_t elemsize = GetElemType()->GetSize();
1718     if (elemsize == 0 || sum == 0) {
1719         return 0;
1720     }
1721     elemsize = RoundUp(elemsize, typeAttrs.GetAlign());
1722     constexpr int64 bitsPerByte = 8;
1723     int64 offset = static_cast<uint64>(sum) * elemsize * static_cast<uint64>(bitsPerByte);
1724     if (GetElemType()->GetKind() == kTypeArray && indexArray.size() > dim) {
1725         std::vector<int64> subIndexArray(indexArray.begin() + dim, indexArray.end());
1726         offset += static_cast<MIRArrayType *>(GetElemType())->GetBitOffsetFromArrayAddress(subIndexArray);
1727     }
1728     return offset;
1729 }
1730 
ElemNumber()1731 size_t MIRArrayType::ElemNumber()
1732 {
1733     size_t elemNum = 1;
1734     for (uint16 id = 0; id < dim; ++id) {
1735         elemNum *= sizeArray[id];
1736     }
1737 
1738     auto elemType = GetElemType();
1739     if (elemType->GetKind() == kTypeArray) {
1740         elemNum *= static_cast<MIRArrayType *>(elemType)->ElemNumber();
1741     }
1742     return elemNum;
1743 }
1744 
GetElemType() const1745 MIRType *MIRFarrayType::GetElemType() const
1746 {
1747     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx);
1748 }
1749 
EqualTo(const MIRType & type) const1750 bool MIRFarrayType::EqualTo(const MIRType &type) const
1751 {
1752     if (type.GetKind() != typeKind) {
1753         return false;
1754     }
1755     const auto &pType = static_cast<const MIRFarrayType &>(type);
1756     return elemTyIdx == pType.GetElemTyIdx();
1757 }
1758 
GetMplTypeName() const1759 std::string MIRFarrayType::GetMplTypeName() const
1760 {
1761     std::stringstream ss;
1762     ss << "<[] ";
1763     MIRType *elemType = GetElemType();
1764     ss << elemType->GetMplTypeName();
1765     ss << ">";
1766     return ss.str();
1767 }
1768 
HasFields() const1769 bool MIRFarrayType::HasFields() const
1770 {
1771     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx);
1772     return elemType->HasFields();
1773 }
1774 
NumberOfFieldIDs() const1775 uint32 MIRFarrayType::NumberOfFieldIDs() const
1776 {
1777     if (fieldsNum != kInvalidFieldNum) {
1778         return fieldsNum;
1779     }
1780     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx);
1781     fieldsNum = elemType->NumberOfFieldIDs();
1782     return fieldsNum;
1783 }
1784 
EmbeddedStructType()1785 MIRStructType *MIRFarrayType::EmbeddedStructType()
1786 {
1787     MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx);
1788     return elemType->EmbeddedStructType();
1789 }
1790 
GetBitOffsetFromArrayAddress(int64 arrayIndex)1791 int64 MIRFarrayType::GetBitOffsetFromArrayAddress(int64 arrayIndex)
1792 {
1793     size_t elemsize = GetElemType()->GetSize();
1794     if (elemsize == 0 || arrayIndex == 0) {
1795         return 0;
1796     }
1797     uint32 elemAlign = GetElemType()->GetAlign();
1798     elemsize = RoundUp(elemsize, elemAlign);
1799     constexpr int64 bitsPerByte = 8;
1800     return arrayIndex * static_cast<int64>(elemsize) * bitsPerByte;
1801 }
1802 
EqualTo(const MIRType & type) const1803 bool MIRFuncType::EqualTo(const MIRType &type) const
1804 {
1805     if (type.GetKind() != typeKind) {
1806         return false;
1807     }
1808     const auto &pType = static_cast<const MIRFuncType &>(type);
1809     return (pType.retTyIdx == retTyIdx && pType.paramTypeList == paramTypeList && pType.funcAttrs == funcAttrs &&
1810             pType.paramAttrsList == paramAttrsList && pType.retAttrs == retAttrs);
1811 }
1812 
TypeCompatible(TyIdx typeIdx1,TyIdx typeIdx2)1813 static bool TypeCompatible(TyIdx typeIdx1, TyIdx typeIdx2)
1814 {
1815     if (typeIdx1 == typeIdx2) {
1816         return true;
1817     }
1818     MIRType *type1 = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx1);
1819     MIRType *type2 = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx2);
1820     if (type1 == nullptr || type2 == nullptr) {
1821         // this means we saw the use of this symbol before def.
1822         return false;
1823     }
1824     while (type1->IsMIRPtrType() || type1->IsMIRArrayType()) {
1825         if (type1->IsMIRPtrType()) {
1826             if (!type2->IsMIRPtrType()) {
1827                 return false;
1828             }
1829             type1 = static_cast<MIRPtrType *>(type1)->GetPointedType();
1830             type2 = static_cast<MIRPtrType *>(type2)->GetPointedType();
1831         } else {
1832             if (!type2->IsMIRArrayType()) {
1833                 return false;
1834             }
1835             type1 = static_cast<MIRArrayType *>(type1)->GetElemType();
1836             type2 = static_cast<MIRArrayType *>(type2)->GetElemType();
1837         }
1838     }
1839     if (type1 == type2) {
1840         return true;
1841     }
1842     if (type1->GetPrimType() == PTY_void || type2->GetPrimType() == PTY_void) {
1843         return true;
1844     }
1845     if (type1->IsIncomplete() || type2->IsIncomplete()) {
1846         return true;
1847     }
1848     return false;
1849 }
1850 
CompatibleWith(const MIRType & type) const1851 bool MIRFuncType::CompatibleWith(const MIRType &type) const
1852 {
1853     if (type.GetKind() != typeKind) {
1854         return false;
1855     }
1856     const auto &pType = static_cast<const MIRFuncType &>(type);
1857     if (!TypeCompatible(pType.retTyIdx, retTyIdx)) {
1858         return false;
1859     }
1860     if (pType.paramTypeList.size() != paramTypeList.size()) {
1861         return false;
1862     }
1863     for (size_t i = 0; i < paramTypeList.size(); i++) {
1864         if (!TypeCompatible(pType.GetNthParamType(i), GetNthParamType(i))) {
1865             return false;
1866         }
1867     }
1868     return true;
1869 }
1870 
EqualTo(const MIRType & type) const1871 bool MIRBitFieldType::EqualTo(const MIRType &type) const
1872 {
1873     if (type.GetKind() != typeKind || type.GetPrimType() != primType) {
1874         return false;
1875     }
1876     const auto &pType = static_cast<const MIRBitFieldType &>(type);
1877     return pType.fieldSize == fieldSize;
1878 }
1879 
EqualTo(const MIRType & type) const1880 bool MIRStructType::EqualTo(const MIRType &type) const
1881 {
1882     if (type.GetKind() != typeKind) {
1883         return false;
1884     }
1885     if (type.GetNameStrIdx() != nameStrIdx) {
1886         return false;
1887     }
1888 
1889     DEBUG_ASSERT(type.IsStructType(), "p is null in MIRStructType::EqualTo");
1890     const MIRStructType *p = static_cast<const MIRStructType *>(&type);
1891     if (typeAttrs != p->typeAttrs) {
1892         return false;
1893     }
1894     if (fields != p->fields) {
1895         return false;
1896     }
1897     if (staticFields != p->staticFields) {
1898         return false;
1899     }
1900     if (parentFields != p->parentFields) {
1901         return false;
1902     }
1903     if (methods != p->methods) {
1904         return false;
1905     }
1906     return true;
1907 }
1908 
GetCompactMplTypeName() const1909 std::string MIRStructType::GetCompactMplTypeName() const
1910 {
1911     return GlobalTables::GetStrTable().GetStringFromStrIdx(nameStrIdx);
1912 }
1913 
GetElemType(uint32 n) const1914 MIRType *MIRStructType::GetElemType(uint32 n) const
1915 {
1916     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetElemTyIdx(n));
1917 }
1918 
GetFieldType(FieldID fieldID)1919 MIRType *MIRStructType::GetFieldType(FieldID fieldID)
1920 {
1921     if (fieldID == 0) {
1922         return this;
1923     }
1924     const FieldPair &fieldPair = TraverseToFieldRef(fieldID);
1925     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldPair.second.first);
1926 }
1927 
IsLocal() const1928 bool MIRStructType::IsLocal() const
1929 {
1930     return GlobalTables::GetGsymTable().GetStIdxFromStrIdx(nameStrIdx).Idx() != 0;
1931 }
1932 
GetMplTypeName() const1933 std::string MIRStructType::GetMplTypeName() const
1934 {
1935     std::stringstream ss;
1936     ss << "<$";
1937     ss << GlobalTables::GetStrTable().GetStringFromStrIdx(nameStrIdx);
1938     ss << ">";
1939     return ss.str();
1940 }
1941 
EqualTo(const MIRType & type) const1942 bool MIRClassType::EqualTo(const MIRType &type) const
1943 {
1944     if (type.GetKind() != typeKind) {
1945         return false;
1946     }
1947     bool structeq = MIRStructType::EqualTo(type);
1948     if (!structeq) {
1949         return false;
1950     }
1951 
1952     const MIRClassType &classty = static_cast<const MIRClassType &>(type);
1953     // classes have parent except empty/thirdparty classes
1954     if (parentTyIdx != classty.parentTyIdx) {
1955         return false;
1956     }
1957 
1958     if (interfacesImplemented != classty.interfacesImplemented) {
1959         return false;
1960     }
1961     if (info != classty.info) {
1962         return false;
1963     }
1964     if (infoIsString != classty.infoIsString) {
1965         return false;
1966     }
1967     return true;
1968 }
1969 
EqualTo(const MIRType & type) const1970 bool MIRInterfaceType::EqualTo(const MIRType &type) const
1971 {
1972     if (type.GetKind() != typeKind) {
1973         return false;
1974     }
1975     bool structeq = MIRStructType::EqualTo(type);
1976     if (!structeq) {
1977         return false;
1978     }
1979 
1980     const MIRInterfaceType &interfacety = static_cast<const MIRInterfaceType &>(type);
1981     if (parentsTyIdx != interfacety.parentsTyIdx) {
1982         return false;
1983     }
1984     if (info != interfacety.info) {
1985         return false;
1986     }
1987     if (infoIsString != interfacety.infoIsString) {
1988         return false;
1989     }
1990     return true;
1991 }
1992 
EqualTo(const MIRType & type) const1993 bool MIRTypeByName::EqualTo(const MIRType &type) const
1994 {
1995     return type.GetKind() == typeKind && type.GetNameStrIdx() == nameStrIdx && type.IsNameIsLocal() == nameIsLocal;
1996 }
1997 
EqualTo(const MIRType & type) const1998 bool MIRTypeParam::EqualTo(const MIRType &type) const
1999 {
2000     return type.GetKind() == typeKind && type.GetNameStrIdx() == nameStrIdx;
2001 }
2002 
EqualTo(const MIRType & type) const2003 bool MIRInstantVectorType::EqualTo(const MIRType &type) const
2004 {
2005     if (type.GetKind() != typeKind) {
2006         return false;
2007     }
2008     const auto &pty = static_cast<const MIRInstantVectorType &>(type);
2009     return (instantVec == pty.GetInstantVec());
2010 }
2011 
EqualTo(const MIRType & type) const2012 bool MIRGenericInstantType::EqualTo(const MIRType &type) const
2013 {
2014     if (!MIRInstantVectorType::EqualTo(type)) {
2015         return false;
2016     }
2017     const auto &pType = static_cast<const MIRGenericInstantType &>(type);
2018     return genericTyIdx == pType.GetGenericTyIdx();
2019 }
2020 
2021 // in the search, curfieldid is being decremented until it reaches 1
TraverseToFieldRef(FieldID & fieldID) const2022 FieldPair MIRStructType::TraverseToFieldRef(FieldID &fieldID) const
2023 {
2024     if (!fields.size()) {
2025         return FieldPair(GStrIdx(0), TyIdxFieldAttrPair(TyIdx(0), FieldAttrs()));
2026     }
2027 
2028     uint32 fieldIdx = 0;
2029     FieldPair curPair = fields[0];
2030     while (fieldID > 1) {
2031         --fieldID;
2032         MIRType *curFieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(curPair.second.first);
2033         MIRStructType *subStructTy = curFieldType->EmbeddedStructType();
2034         if (subStructTy != nullptr) {
2035             curPair = subStructTy->TraverseToFieldRef(fieldID);
2036             if (fieldID == 1 && curPair.second.first != TyIdx(0)) {
2037                 return curPair;
2038             }
2039         }
2040         ++fieldIdx;
2041         if (fieldIdx == fields.size()) {
2042             return FieldPair(GStrIdx(0), TyIdxFieldAttrPair(TyIdx(0), FieldAttrs()));
2043         }
2044         curPair = fields[fieldIdx];
2045     }
2046     return curPair;
2047 }
2048 
TraverseToField(FieldID fieldID) const2049 FieldPair MIRStructType::TraverseToField(FieldID fieldID) const
2050 {
2051     if (fieldID >= 0) {
2052         return TraverseToFieldRef(fieldID);
2053     }
2054     // in parentfields
2055     uint32 parentFieldIdx = -fieldID;
2056     if (parentFields.empty() || parentFieldIdx > parentFields.size()) {
2057         return {GStrIdx(0), TyIdxFieldAttrPair(TyIdx(0), FieldAttrs())};
2058     }
2059     return parentFields[parentFieldIdx - 1];
2060 }
2061 
TraverseToFieldInFields(const FieldVector & fields,const GStrIdx & fieldStrIdx,FieldPair & field)2062 static bool TraverseToFieldInFields(const FieldVector &fields, const GStrIdx &fieldStrIdx, FieldPair &field)
2063 {
2064     for (auto &fp : fields) {
2065         if (fp.first == fieldStrIdx) {
2066             field = fp;
2067             return true;
2068         }
2069     }
2070     return false;
2071 }
2072 
TraverseToField(GStrIdx fieldStrIdx) const2073 FieldPair MIRStructType::TraverseToField(GStrIdx fieldStrIdx) const
2074 {
2075     FieldPair fieldPair;
2076     if ((!fields.empty() && TraverseToFieldInFields(fields, fieldStrIdx, fieldPair)) ||
2077         (!staticFields.empty() && TraverseToFieldInFields(staticFields, fieldStrIdx, fieldPair)) ||
2078         TraverseToFieldInFields(parentFields, fieldStrIdx, fieldPair)) {
2079         return fieldPair;
2080     }
2081     return {GStrIdx(0), TyIdxFieldAttrPair(TyIdx(0), FieldAttrs())};
2082 }
2083 
HasVolatileFieldInFields(const FieldVector & fieldsOfStruct) const2084 bool MIRStructType::HasVolatileFieldInFields(const FieldVector &fieldsOfStruct) const
2085 {
2086     for (const auto &field : fieldsOfStruct) {
2087         if (field.second.second.GetAttr(FLDATTR_volatile) ||
2088             GlobalTables::GetTypeTable().GetTypeFromTyIdx(field.second.first)->HasVolatileField()) {
2089             hasVolatileField = true;
2090             return true;
2091         }
2092     }
2093     hasVolatileField = false;
2094     return false;
2095 }
2096 
2097 // go through all the fields to check if there is volatile attribute set;
HasVolatileField() const2098 bool MIRStructType::HasVolatileField() const
2099 {
2100     if (hasVolatileFieldSet) {
2101         return hasVolatileField;
2102     }
2103     hasVolatileFieldSet = true;
2104     return HasVolatileFieldInFields(fields) || HasVolatileFieldInFields(parentFields);
2105 }
2106 
GetBitOffsetFromUnionBaseAddr(FieldID fieldID)2107 int64 MIRStructType::GetBitOffsetFromUnionBaseAddr(FieldID fieldID)
2108 {
2109     CHECK_FATAL(fieldID <= static_cast<FieldID>(NumberOfFieldIDs()),
2110                 "GetBitOffsetFromUnionBaseAddr: fieldID too large");
2111     if (fieldID == 0) {
2112         return 0;
2113     }
2114 
2115     FieldID curFieldID = 1;
2116     FieldVector fieldPairs = GetFields();
2117     // for unions, bitfields are treated as non-bitfields
2118     for (FieldPair field : fieldPairs) {
2119         TyIdx fieldTyIdx = field.second.first;
2120         MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldTyIdx);
2121         if (curFieldID == fieldID) {
2122             // target field id is found
2123             // offset of field in union direcly(i.e. not embedded in other struct) is zero.
2124             return 0;
2125         } else {
2126             MIRStructType *subStructType = fieldType->EmbeddedStructType();
2127             if (subStructType == nullptr) {
2128                 // field is not a complex structure, no extra field id in it, just inc and continue to next field
2129                 curFieldID++;
2130             } else {
2131                 // if target field id is in the embedded structure, we should go into it by recursively call
2132                 // otherwise, just add the field-id number of the embedded structure, and continue to next field
2133                 if ((curFieldID + static_cast<FieldID>(subStructType->NumberOfFieldIDs())) < fieldID) {
2134                     // 1 represents subStructType itself
2135                     curFieldID += static_cast<FieldID>(subStructType->NumberOfFieldIDs()) + 1;
2136                 } else {
2137                     return subStructType->GetBitOffsetFromBaseAddr(fieldID - curFieldID);
2138                 }
2139             }
2140         }
2141     }
2142     CHECK_FATAL(false, "GetBitOffsetFromUnionBaseAddr() fails to find field");
2143     return kOffsetUnknown;
2144 }
2145 
GetBitOffsetFromStructBaseAddr(FieldID fieldID)2146 int64 MIRStructType::GetBitOffsetFromStructBaseAddr(FieldID fieldID)
2147 {
2148     CHECK_FATAL(fieldID <= static_cast<FieldID>(NumberOfFieldIDs()),
2149                 "GetBitOffsetFromUnionBaseAddr: fieldID too large");
2150     if (fieldID == 0) {
2151         return 0;
2152     }
2153 
2154     uint64 allocedSize = 0;  // space need for all fields before currentField
2155     uint64 allocedBitSize = 0;
2156     FieldID curFieldID = 1;
2157     constexpr uint32 bitsPerByte = 8;  // 8 bits per byte
2158     FieldVector fieldPairs = GetFields();
2159     // process the struct fields
2160     // There are 3 possible kinds of field in a MIRStructureType:
2161     //  case 1 : bitfield (including zero-width bitfield);
2162     //  case 2 : primtive field;
2163     //  case 3 : normal (empty/non-empty) structure(struct/union) field;
2164     for (FieldPair field : fieldPairs) {
2165         TyIdx fieldTyIdx = field.second.first;
2166         auto fieldAttr = field.second.second;
2167         MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldTyIdx);
2168         uint32 fieldBitSize = static_cast<MIRBitFieldType *>(fieldType)->GetFieldSize();
2169         size_t fieldTypeSize = fieldType->GetSize();
2170         uint32 fieldTypeSizeBits = static_cast<uint32>(fieldTypeSize) * bitsPerByte;
2171         auto originAlign = fieldType->GetAlign();
2172         uint32 fieldAlign = fieldAttr.IsPacked() ? 1 : std::min(GetTypeAttrs().GetPack(), originAlign);
2173         auto fieldAlignBits = fieldAlign * bitsPerByte;
2174         // case 1 : bitfield (including zero-width bitfield);
2175         if (fieldType->GetKind() == kTypeBitField) {
2176             fieldTypeSizeBits = static_cast<uint32>(GetPrimTypeSize(fieldType->GetPrimType())) * bitsPerByte;
2177             // Is this field is crossing the align boundary of its base type?
2178             // for example:
2179             // struct Expamle {
2180             //      int32 fld1 : 30
2181             //      int32 fld2 : 3;  // 30 + 3 > 32(= int32 align), cross the align boundary, start from next int32
2182             //      boundary
2183             // }
2184             //
2185             // Is field a zero-width bit field?
2186             // Refer to C99 standard (§6.7.2.1) :
2187             // > As a special case, a bit-field structure member with a width of 0 indicates that no further
2188             // > bit-field is to be packed into the unit in which the previous bit-field, if any, was placed.
2189             //
2190             // We know that A zero-width bit field can cause the next field to be aligned on the next container
2191             // boundary where the container is the same size as the underlying type of the bit field.
2192             // for example:
2193             // struct Example {
2194             //     int32 fld1 : 5
2195             //     int32      : 0 // force the next field to be aligned on int32 align boundary
2196             //     int32 fld3 : 4
2197             // }
2198             if ((!GetTypeAttrs().IsPacked() && ((allocedBitSize / fieldTypeSizeBits) !=
2199                                                 ((allocedBitSize + fieldBitSize - 1u) / fieldTypeSizeBits))) ||
2200                 fieldBitSize == 0) {
2201                 // the field is crossing the align boundary of its base type;
2202                 // align alloced_size_in_bits to fieldAlign
2203                 allocedBitSize = RoundUp(allocedBitSize, fieldTypeSizeBits);
2204             }
2205 
2206             // target field id is found
2207             if (curFieldID == fieldID) {
2208                 return static_cast<int64>(allocedBitSize);
2209             } else {
2210                 ++curFieldID;
2211             }
2212             allocedBitSize += fieldBitSize;
2213             fieldAlignBits = (fieldAlignBits) != 0 ? fieldAlignBits : fieldTypeSizeBits;
2214             allocedSize = std::max(allocedSize, RoundUp(allocedBitSize, fieldAlignBits) / bitsPerByte);
2215             continue;
2216         }  // case 1 end
2217 
2218         bool leftOverBits = false;
2219         uint64 offset = 0;
2220         // no bit field before current field
2221         if (allocedBitSize == allocedSize * bitsPerByte) {
2222             allocedSize = RoundUp(allocedSize, fieldAlign);
2223             offset = allocedSize;
2224         } else {
2225             // still some leftover bits on allocated words, we calculate things based on bits then.
2226             if (allocedBitSize / fieldAlignBits != (allocedBitSize + fieldTypeSizeBits - 1) / fieldAlignBits) {
2227                 // the field is crossing the align boundary of its base type
2228                 allocedBitSize = RoundUp(allocedBitSize, static_cast<uint32>(fieldAlignBits));
2229             }
2230             allocedSize = RoundUp(allocedSize, fieldAlign);
2231             offset = (allocedBitSize / fieldAlignBits) * fieldAlign;
2232             leftOverBits = true;
2233         }
2234         // target field id is found
2235         if (curFieldID == fieldID) {
2236             return static_cast<int64>(offset * bitsPerByte);
2237         }
2238         MIRStructType *subStructType = fieldType->EmbeddedStructType();
2239         // case 2 : primtive field;
2240         if (subStructType == nullptr) {
2241             ++curFieldID;
2242         } else {
2243             // case 3 : normal (empty/non-empty) structure(struct/union) field;
2244             // if target field id is in the embedded structure, we should go into it by recursively call
2245             // otherwise, just add the field-id number of the embedded structure, and continue to next field
2246             if ((curFieldID + static_cast<FieldID>(subStructType->NumberOfFieldIDs())) < fieldID) {
2247                 curFieldID +=
2248                     static_cast<FieldID>(subStructType->NumberOfFieldIDs()) + 1;  // 1 represents subStructType itself
2249             } else {
2250                 int64 result = subStructType->GetBitOffsetFromBaseAddr(fieldID - curFieldID);
2251                 return result + static_cast<int64>(allocedSize * bitsPerByte);
2252             }
2253         }
2254 
2255         if (leftOverBits) {
2256             allocedBitSize += fieldTypeSizeBits;
2257             allocedSize =
2258                 std::max(allocedSize, RoundUp(allocedBitSize, static_cast<uint32>(fieldAlignBits)) / bitsPerByte);
2259         } else {
2260             allocedSize += fieldTypeSize;
2261             allocedBitSize = allocedSize * bitsPerByte;
2262         }
2263     }
2264     CHECK_FATAL(false, "GetBitOffsetFromStructBaseAddr() fails to find field");
2265     return kOffsetUnknown;
2266 }
2267 
GetBitOffsetFromBaseAddr(FieldID fieldID)2268 int64 MIRStructType::GetBitOffsetFromBaseAddr(FieldID fieldID)
2269 {
2270     CHECK_FATAL(fieldID <= static_cast<FieldID>(NumberOfFieldIDs()), "GetBitOffsetFromBaseAddr: fieldID too large");
2271     if (fieldID == 0) {
2272         return 0;
2273     }
2274     switch (GetKind()) {
2275         case kTypeClass: {
2276             // NYI: should know class layout, for different language, the result is different
2277             return kOffsetUnknown;  // Invalid offset
2278         }
2279         case kTypeUnion: {
2280             return GetBitOffsetFromUnionBaseAddr(fieldID);
2281         }
2282         case kTypeStruct: {
2283             return GetBitOffsetFromStructBaseAddr(fieldID);
2284         }
2285         default: {
2286             CHECK_FATAL(false, "Wrong type kind for MIRStructType!");
2287         }
2288     }
2289     CHECK_FATAL(false, "Should never reach here!");
2290     return kOffsetUnknown;
2291 }
2292 
2293 // Whether the memory layout of struct has paddings
HasPadding() const2294 bool MIRStructType::HasPadding() const
2295 {
2296     size_t sumValidSize = 0;
2297     for (uint32 i = 0; i < fields.size(); ++i) {
2298         TyIdxFieldAttrPair pair = GetTyidxFieldAttrPair(i);
2299         MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pair.first);
2300         if (fieldType->IsStructType() && static_cast<MIRStructType *>(fieldType)->HasPadding()) {
2301             return true;
2302         }
2303         sumValidSize += fieldType->GetSize();
2304     }
2305     if (sumValidSize < this->GetSize()) {
2306         return true;
2307     }
2308     return false;
2309 }
2310 
2311 // set hasVolatileField to true if parent type has volatile field, otherwise flase.
ParentTypeHasVolatileField(const TyIdx parentTyIdx,bool & hasVolatileField)2312 static bool ParentTypeHasVolatileField(const TyIdx parentTyIdx, bool &hasVolatileField)
2313 {
2314     hasVolatileField = (GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx)->HasVolatileField());
2315     return hasVolatileField;
2316 }
2317 
2318 // go through all the fields to check if there is volatile attribute set;
HasVolatileField() const2319 bool MIRClassType::HasVolatileField() const
2320 {
2321     return MIRStructType::HasVolatileField() ||
2322            (parentTyIdx != 0u && ParentTypeHasVolatileField(parentTyIdx, hasVolatileField));
2323 }
2324 
2325 // go through all the fields to check if there is volatile attribute set;
HasVolatileField() const2326 bool MIRInterfaceType::HasVolatileField() const
2327 {
2328     if (MIRStructType::HasVolatileField()) {
2329         return true;
2330     }
2331     for (TyIdx parentTypeIdx : parentsTyIdx) {
2332         if (ParentTypeHasVolatileField(parentTypeIdx, hasVolatileField)) {
2333             return true;
2334         }
2335     }
2336     return false;
2337 }
2338 
HasTypeParamInFields(const FieldVector & fieldsOfStruct) const2339 bool MIRStructType::HasTypeParamInFields(const FieldVector &fieldsOfStruct) const
2340 {
2341     for (const FieldPair &field : fieldsOfStruct) {
2342         if (field.second.second.GetAttr(FLDATTR_generic)) {
2343             return true;
2344         }
2345     }
2346     return false;
2347 }
2348 
2349 // go through all the fields to check if there is generic attribute set;
HasTypeParam() const2350 bool MIRStructType::HasTypeParam() const
2351 {
2352     return HasTypeParamInFields(fields) || HasTypeParamInFields(parentFields);
2353 }
2354 
HasTypeParam() const2355 bool MIRClassType::HasTypeParam() const
2356 {
2357     return MIRStructType::HasTypeParam() ||
2358            (parentTyIdx != 0u && GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx)->HasTypeParam());
2359 }
2360 
HasTypeParam() const2361 bool MIRInterfaceType::HasTypeParam() const
2362 {
2363     if (MIRStructType::HasTypeParam()) {
2364         return true;
2365     }
2366     // check if the parent classes have type parameter
2367     for (TyIdx parentTypeIdx : parentsTyIdx) {
2368         if (GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTypeIdx)->HasTypeParam()) {
2369             return true;
2370         }
2371     }
2372     return false;
2373 }
2374 
NumberOfFieldIDs() const2375 uint32 MIRClassType::NumberOfFieldIDs() const
2376 {
2377     if (fieldsNum != kInvalidFieldNum) {
2378         return fieldsNum;
2379     }
2380     size_t parentFieldIDs = 0;
2381     if (parentTyIdx != TyIdx(0)) {
2382         MIRType *parentty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx);
2383         parentFieldIDs = parentty->NumberOfFieldIDs();
2384     }
2385     fieldsNum = parentFieldIDs + MIRStructType::NumberOfFieldIDs();
2386     return fieldsNum;
2387 }
2388 
TraverseToFieldRef(FieldID & fieldID) const2389 FieldPair MIRClassType::TraverseToFieldRef(FieldID &fieldID) const
2390 {
2391     if (parentTyIdx != 0u) {
2392         auto *parentClassType = static_cast<MIRClassType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx));
2393         if (parentClassType != nullptr) {
2394             --fieldID;
2395             const FieldPair &curPair = parentClassType->TraverseToFieldRef(fieldID);
2396             if (fieldID == 1 && curPair.second.first != 0u) {
2397                 return curPair;
2398             }
2399         }
2400     }
2401     return MIRStructType::TraverseToFieldRef(fieldID);
2402 }
2403 
2404 // fields in interface are all static and are global, won't be accessed through fields
TraverseToFieldRef(FieldID & fieldID) const2405 FieldPair MIRInterfaceType::TraverseToFieldRef(FieldID &fieldID) const
2406 {
2407     return {GStrIdx(0), TyIdxFieldAttrPair(TyIdx(0), FieldAttrs())};
2408 }
2409 
IsPointedTypeVolatile(int fieldID) const2410 bool MIRPtrType::IsPointedTypeVolatile(int fieldID) const
2411 {
2412     if (typeAttrs.GetAttr(ATTR_volatile)) {
2413         return true;
2414     }
2415     MIRType *pointedTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetPointedTyIdx());
2416     return pointedTy->IsVolatile(fieldID);
2417 }
2418 
IsUnsafeType() const2419 bool MIRPtrType::IsUnsafeType() const
2420 {
2421     if (GetTypeAttrs().GetAttr(ATTR_may_alias)) {
2422         return true;
2423     }
2424     // Check for <* void>/<* i8/u8>
2425     MIRType *pointedType = GetPointedType();
2426     while (pointedType->IsMIRPtrType()) {
2427         pointedType = static_cast<MIRPtrType *>(pointedType)->GetPointedType();
2428     }
2429     return (pointedType->GetPrimType() == PTY_void || pointedType->GetSize() == 1);
2430 }
2431 
IsVoidPointer() const2432 bool MIRPtrType::IsVoidPointer() const
2433 {
2434     return GlobalTables::GetTypeTable().GetVoidPtr() == this;
2435 }
2436 
GetSize() const2437 size_t MIRPtrType::GetSize() const
2438 {
2439     return GetPointerSize();
2440 }
GetAlign() const2441 uint32 MIRPtrType::GetAlign() const
2442 {
2443     return GetPointerSize();
2444 }
2445 
GetPointedTyIdxFldAttrPairWithFieldID(FieldID fldId) const2446 TyIdxFieldAttrPair MIRPtrType::GetPointedTyIdxFldAttrPairWithFieldID(FieldID fldId) const
2447 {
2448     if (fldId == 0) {
2449         return TyIdxFieldAttrPair(pointedTyIdx, FieldAttrs());
2450     }
2451     MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
2452     MIRStructType *structTy = ty->EmbeddedStructType();
2453     if (structTy == nullptr) {
2454         // this can happen due to casting in C; just return the pointed to type
2455         return TyIdxFieldAttrPair(pointedTyIdx, FieldAttrs());
2456     }
2457     return structTy->TraverseToField(fldId).second;
2458 }
2459 
GetPointedTyIdxWithFieldID(FieldID fieldID) const2460 TyIdx MIRPtrType::GetPointedTyIdxWithFieldID(FieldID fieldID) const
2461 {
2462     return GetPointedTyIdxFldAttrPairWithFieldID(fieldID).first;
2463 }
2464 
GetMplTypeName() const2465 std::string MIRPtrType::GetMplTypeName() const
2466 {
2467     std::stringstream ss;
2468     ss << "<* ";
2469     MIRType *pointedType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
2470     CHECK_FATAL(pointedType != nullptr, "invalid ptr type");
2471     ss << pointedType->GetMplTypeName();
2472     ss << ">";
2473     return ss.str();
2474 }
2475 
GetCompactMplTypeName() const2476 std::string MIRPtrType::GetCompactMplTypeName() const
2477 {
2478     MIRType *pointedType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
2479     CHECK_FATAL(pointedType != nullptr, "invalid ptr type");
2480     return pointedType->GetCompactMplTypeName();
2481 }
2482 
GetPointedFuncType() const2483 MIRFuncType *MIRPtrType::GetPointedFuncType() const
2484 {
2485     MIRType *pointedType = GetPointedType();
2486     if (pointedType->GetKind() == kTypeFunction) {
2487         return static_cast<MIRFuncType *>(pointedType);
2488     }
2489     if (pointedType->GetKind() == kTypePointer) {
2490         MIRPtrType *pointedPtrType = static_cast<MIRPtrType *>(pointedType);
2491         if (pointedPtrType->GetPointedType()->GetKind() == kTypeFunction) {
2492             return static_cast<MIRFuncType *>(pointedPtrType->GetPointedType());
2493         }
2494     }
2495     return nullptr;
2496 }
2497 
NumberOfFieldIDs() const2498 uint32 MIRStructType::NumberOfFieldIDs() const
2499 {
2500     if (fieldsNum != kInvalidFieldNum) {
2501         return fieldsNum;
2502     }
2503     fieldsNum = 0;
2504     for (FieldPair curpair : fields) {
2505         ++fieldsNum;
2506         MIRType *curfieldtype = GlobalTables::GetTypeTable().GetTypeFromTyIdx(curpair.second.first);
2507         fieldsNum += curfieldtype->NumberOfFieldIDs();
2508     }
2509     return fieldsNum;
2510 }
2511 
ConvertToTypeAttrs()2512 TypeAttrs FieldAttrs::ConvertToTypeAttrs()
2513 {
2514     TypeAttrs attr;
2515     constexpr uint32 maxAttrNum = 64;
2516     for (uint32 i = 0; i < maxAttrNum; ++i) {
2517         if ((attrFlag & (1ULL << i)) == 0) {
2518             continue;
2519         }
2520         auto attrKind = static_cast<FieldAttrKind>(i);
2521         switch (attrKind) {
2522 #define FIELD_ATTR
2523 #define ATTR(STR)                 \
2524     case FLDATTR_##STR:           \
2525         attr.SetAttr(ATTR_##STR); \
2526         break;
2527 #include "all_attributes.def"
2528 #undef ATTR
2529 #undef FIELD_ATTR
2530             default:
2531                 DEBUG_ASSERT(false, "unknown TypeAttrs");
2532                 break;
2533         }
2534     }
2535     return attr;
2536 }
2537 
GetElemType(const MIRType & arrayType)2538 MIRType *GetElemType(const MIRType &arrayType)
2539 {
2540     if (arrayType.GetKind() == kTypeArray) {
2541         return static_cast<const MIRArrayType &>(arrayType).GetElemType();
2542     } else if (arrayType.GetKind() == kTypeFArray) {
2543         return static_cast<const MIRFarrayType &>(arrayType).GetElemType();
2544     } else if (arrayType.GetKind() == kTypeJArray) {
2545         return static_cast<const MIRJarrayType &>(arrayType).GetElemType();
2546     }
2547     return nullptr;
2548 }
2549 }  // namespace maple
2550 #endif  // MIR_FEATURE_FULL
2551