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