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_builder.h"
18 #if MIR_FEATURE_FULL
19
20 namespace maple {
21 #define LOAD_PRIMARY_TYPE_PROPERTY
22 #include "prim_types.def"
23
24 #define LOAD_ALGO_PRIMARY_TYPE
GetPrimitiveTypeProperty(PrimType pType)25 const PrimitiveTypeProperty &GetPrimitiveTypeProperty(PrimType pType)
26 {
27 switch (pType) {
28 case PTY_begin:
29 return PTProperty_begin;
30 #define PRIMTYPE(P) \
31 case PTY_##P: \
32 return PTProperty_##P;
33 #include "prim_types.def"
34 #undef PRIMTYPE
35 case PTY_end:
36 default:
37 return PTProperty_end;
38 }
39 }
40
GetRegPrimType(PrimType primType)41 PrimType GetRegPrimType(PrimType primType)
42 {
43 switch (primType) {
44 case PTY_i8:
45 case PTY_i16:
46 return PTY_i32;
47 case PTY_u1:
48 case PTY_u8:
49 case PTY_u16:
50 return PTY_u32;
51 default:
52 return primType;
53 }
54 }
55
GetIntegerPrimTypeBySizeAndSign(size_t sizeBit,bool isSign)56 PrimType GetIntegerPrimTypeBySizeAndSign(size_t sizeBit, bool isSign)
57 {
58 switch (sizeBit) {
59 case k1BitSize: {
60 if (isSign) {
61 return PTY_begin; // There is no 'i1' type
62 }
63 return PTY_u1;
64 }
65 case k8BitSize: {
66 return isSign ? PTY_i8 : PTY_u8;
67 }
68 case k16BitSize: {
69 return isSign ? PTY_i16 : PTY_u16;
70 }
71 case k32BitSize: {
72 return isSign ? PTY_i32 : PTY_u32;
73 }
74 case k64BitSize: {
75 return isSign ? PTY_i64 : PTY_u64;
76 }
77 default: {
78 return PTY_begin; // Invalid integer type
79 }
80 }
81 }
82
IsNoCvtNeeded(PrimType toType,PrimType fromType)83 bool IsNoCvtNeeded(PrimType toType, PrimType fromType)
84 {
85 if (toType == fromType) {
86 return true;
87 }
88 switch (toType) {
89 case PTY_i32:
90 return fromType == PTY_i16 || fromType == PTY_i8;
91 case PTY_u32:
92 return fromType == PTY_u16 || fromType == PTY_u8;
93 case PTY_u1:
94 case PTY_u8:
95 case PTY_u16:
96 return fromType == PTY_u32;
97 case PTY_i8:
98 case PTY_i16:
99 return fromType == PTY_i32;
100 case PTY_i64:
101 case PTY_u64:
102 case PTY_a64:
103 case PTY_ptr:
104 return fromType == PTY_ptr || fromType == PTY_u64 || fromType == PTY_a64 || fromType == PTY_i64;
105 default:
106 return false;
107 }
108 }
109
GetPointerSize()110 uint8 GetPointerSize()
111 {
112 #if TARGX86 || TARGARM32 || TARGVM
113 return k4ByteSize;
114 #elif TARGX86_64 || TARGAARCH64
115 if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
116 return k8ByteSize;
117 } else if (Triple::GetTriple().GetArch() == Triple::ArchType::aarch64) {
118 uint8 size = (Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) ? k4ByteSize : k8ByteSize;
119 return size;
120 } else {
121 CHECK_FATAL(false, "Unsupported target");
122 }
123 #else
124 #error "Unsupported target"
125 #endif
126 }
127
GetLoweredPtrType()128 PrimType GetLoweredPtrType()
129 {
130 #if TARGX86_64 || TARGAARCH64
131 if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
132 return PTY_a64;
133 } else if (Triple::GetTriple().GetArch() == Triple::ArchType::aarch64) {
134 auto pty = PTY_a64;
135 return pty;
136 } else {
137 CHECK_FATAL(false, "Unsupported target");
138 }
139 #else
140 #error "Unsupported target"
141 #endif
142 }
143
GetExactPtrPrimType()144 PrimType GetExactPtrPrimType()
145 {
146 return PTY_a64;
147 }
148
149 // answer in bytes; 0 if unknown
GetPrimTypeSize(PrimType primType)150 uint32 GetPrimTypeSize(PrimType primType)
151 {
152 switch (primType) {
153 case PTY_void:
154 return k0BitSize;
155 case PTY_ptr:
156 case PTY_ref:
157 return GetPointerSize();
158 case PTY_u1:
159 case PTY_i8:
160 case PTY_u8:
161 return k1BitSize;
162 case PTY_i16:
163 case PTY_u16:
164 return k2BitSize;
165 case PTY_f32:
166 case PTY_i32:
167 case PTY_u32:
168 return k4BitSize;
169 case PTY_a64:
170 case PTY_f64:
171 case PTY_i64:
172 case PTY_u64:
173 return k8BitSize;
174 default:
175 return k0BitSize;
176 }
177 }
178
179 // return the unsigned version that has the same size
GetUnsignedPrimType(PrimType pty)180 PrimType GetUnsignedPrimType(PrimType pty)
181 {
182 switch (pty) {
183 case PTY_i64:
184 return PTY_u64;
185 case PTY_i8:
186 return PTY_u8;
187 case PTY_i16:
188 return PTY_u16;
189 case PTY_i32:
190 return PTY_u32;
191 default:;
192 }
193 return pty;
194 }
195
196 #ifdef ARK_LITECG_DEBUG
GetPrimTypeName(PrimType primType)197 const char *GetPrimTypeName(PrimType primType)
198 {
199 #define LOAD_ALGO_PRIMARY_TYPE
200 switch (primType) {
201 case kPtyInvalid:
202 return "kPtyInvalid";
203 #define PRIMTYPE(P) \
204 case PTY_##P: \
205 return #P;
206 #include "prim_types.def"
207 #undef PRIMTYPE
208 case kPtyDerived:
209 return "derived"; // just for test: no primitive type for derived
210 default:
211 return "kPtyInvalid";
212 }
213 // SIMD types to be defined
214 }
215
DumpAttributes() const216 void StmtAttrs::DumpAttributes() const
217 {
218 #define STMT_ATTR
219 #define STRING(s) #s
220 #define ATTR(AT) \
221 if (GetAttr(STMTATTR_##AT)) \
222 LogInfo::MapleLogger() << STRING(AT);
223 #include "all_attributes.def"
224 #undef ATTR
225 #undef STMT_ATTR
226 }
227
DumpAttributes() const228 void TypeAttrs::DumpAttributes() const
229 {
230 // dump attr without content
231 #define TYPE_ATTR
232 #define NOCONTENT_ATTR
233 #define STRING(s) #s
234 #define ATTR(AT) \
235 if (GetAttr(ATTR_##AT)) \
236 LogInfo::MapleLogger() << " " << STRING(AT);
237 #include "all_attributes.def"
238 #undef ATTR
239 #undef NOCONTENT_ATTR
240 #undef TYPE_ATTR
241 // dump attr with content
242 if (attrAlign) {
243 LogInfo::MapleLogger() << " align(" << GetAlign() << ")";
244 }
245 if (GetAttr(ATTR_pack) && GetPack() != 0) {
246 LogInfo::MapleLogger() << " pack(" << GetPack() << ")";
247 }
248 }
249 #endif
250
251 #ifdef ARK_LITECG_DEBUG
Dump(int indent,bool dontUseName) const252 void MIRType::Dump(int indent, bool dontUseName) const
253 {
254 LogInfo::MapleLogger() << GetPrimTypeName(primType);
255 }
256
DumpAsCxx(int indent) const257 void MIRType::DumpAsCxx(int indent) const
258 {
259 switch (primType) {
260 case PTY_void:
261 LogInfo::MapleLogger() << "void";
262 break;
263 case PTY_i8:
264 LogInfo::MapleLogger() << "int8 ";
265 break;
266 case PTY_i16:
267 LogInfo::MapleLogger() << "int16";
268 break;
269 case PTY_i32:
270 LogInfo::MapleLogger() << "int32";
271 break;
272 case PTY_i64:
273 LogInfo::MapleLogger() << "int64";
274 break;
275 case PTY_u8:
276 LogInfo::MapleLogger() << "uint8";
277 break;
278 case PTY_u16:
279 LogInfo::MapleLogger() << "uint16";
280 break;
281 case PTY_u32:
282 LogInfo::MapleLogger() << "uint32";
283 break;
284 case PTY_u64:
285 LogInfo::MapleLogger() << "uint64";
286 break;
287 case PTY_u1:
288 LogInfo::MapleLogger() << "bool ";
289 break;
290 case PTY_ptr:
291 LogInfo::MapleLogger() << "void* ";
292 break;
293 case PTY_ref:
294 LogInfo::MapleLogger() << "void* ";
295 break;
296 case PTY_a64:
297 LogInfo::MapleLogger() << "void* ";
298 break;
299 case PTY_f32:
300 LogInfo::MapleLogger() << "float ";
301 break;
302 case PTY_f64:
303 LogInfo::MapleLogger() << "double";
304 break;
305 default:
306 DEBUG_ASSERT(false, "not yet implemented");
307 }
308 }
309 #endif
310
311 #ifdef ARK_LITECG_DEBUG
DumpTypeName(GStrIdx strIdx,bool isLocal)312 inline void DumpTypeName(GStrIdx strIdx, bool isLocal)
313 {
314 LogInfo::MapleLogger() << ((isLocal) ? "%" : "$") << GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx);
315 }
316
CheckAndDumpTypeName(GStrIdx strIdx,bool isLocal)317 static bool CheckAndDumpTypeName(GStrIdx strIdx, bool isLocal)
318 {
319 if (strIdx == 0u) {
320 return false;
321 }
322 LogInfo::MapleLogger() << "<";
323 DumpTypeName(strIdx, isLocal);
324 LogInfo::MapleLogger() << ">";
325 return true;
326 }
327
Dump(int indent,bool dontUseName) const328 void MIRFuncType::Dump(int indent, bool dontUseName) const
329 {
330 if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
331 return;
332 }
333 LogInfo::MapleLogger() << "<func";
334 funcAttrs.DumpAttributes();
335 LogInfo::MapleLogger() << " (";
336 size_t size = paramTypeList.size();
337 for (size_t i = 0; i < size; ++i) {
338 GlobalTables::GetTypeTable().GetTypeFromTyIdx(paramTypeList[i])->Dump(indent + 1);
339 if (i < paramAttrsList.size()) {
340 paramAttrsList[i].DumpAttributes();
341 }
342 if (size - 1 != i) {
343 LogInfo::MapleLogger() << ",";
344 }
345 }
346 if (IsVarargs()) {
347 LogInfo::MapleLogger() << ", ...";
348 }
349 LogInfo::MapleLogger() << ") ";
350 GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx)->Dump(indent + 1);
351 retAttrs.DumpAttributes();
352 LogInfo::MapleLogger() << ">";
353 }
354 #endif
355
RoundUpConst(uint64 offset,uint32 align)356 static constexpr uint64 RoundUpConst(uint64 offset, uint32 align)
357 {
358 uint64 tempFirst = static_cast<uint64>(-align);
359 CHECK_FATAL((offset <= UINT64_MAX - align), "must not be zero");
360 DEBUG_ASSERT(offset + align > 0, "offset and align should not be zero");
361 uint64 tempSecond = static_cast<uint64>(offset + align - 1);
362 return tempFirst & tempSecond;
363 }
364
RoundUp(uint64 offset,uint32 align)365 static inline uint64 RoundUp(uint64 offset, uint32 align)
366 {
367 if (align == 0) {
368 return offset;
369 }
370 return RoundUpConst(offset, align);
371 }
372
GetSize() const373 size_t MIRArrayType::GetSize() const
374 {
375 if (size != kInvalidSize) {
376 return size;
377 }
378 size_t elemsize = GetElemType()->GetSize();
379 if (elemsize == 0) {
380 return 0;
381 }
382 elemsize = RoundUp(elemsize, typeAttrs.GetAlign());
383 size_t numelems = sizeArray[0];
384 for (uint16 i = 1; i < dim; i++) {
385 numelems *= sizeArray[i];
386 }
387 size = elemsize * numelems;
388 return size;
389 }
390
GetAlign() const391 uint32 MIRArrayType::GetAlign() const
392 {
393 if (GetSize() == 0) {
394 return typeAttrs.GetAlign();
395 }
396 return std::max(GetElemType()->GetAlign(), typeAttrs.GetAlign());
397 }
398
399 #ifdef ARK_LITECG_DEBUG
Dump(int indent,bool dontUseName) const400 void MIRArrayType::Dump(int indent, bool dontUseName) const
401 {
402 if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
403 return;
404 }
405 LogInfo::MapleLogger() << "<";
406 for (uint16 i = 0; i < dim; ++i) {
407 LogInfo::MapleLogger() << "[" << GetSizeArrayItem(i) << "]";
408 }
409 LogInfo::MapleLogger() << " ";
410 GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx)->Dump(indent + 1);
411 GetTypeAttrs().DumpAttributes();
412 LogInfo::MapleLogger() << ">";
413 }
414 #endif
415
GetPointedType() const416 MIRType *MIRPtrType::GetPointedType() const
417 {
418 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
419 }
420
IsVolatile(int fieldID) const421 bool MIRType::IsVolatile(int fieldID) const
422 {
423 CHECK_FATAL(fieldID == 0, "fieldID must be 0");
424 return HasVolatileField();
425 }
426
HasTypeParam() const427 bool MIRPtrType::HasTypeParam() const
428 {
429 return GetPointedType()->HasTypeParam();
430 }
431
432 #ifdef ARK_LITECG_DEBUG
PointsToConstString() const433 bool MIRPtrType::PointsToConstString() const
434 {
435 return false;
436 }
437
Dump(int indent,bool dontUseName) const438 void MIRPtrType::Dump(int indent, bool dontUseName) const
439 {
440 if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) {
441 return;
442 }
443 MIRType *pointedType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointedTyIdx);
444 if (pointedType->GetKind() == kTypeFunction) { // no * for function pointer
445 pointedType->Dump(indent);
446 } else {
447 LogInfo::MapleLogger() << "<* ";
448 pointedType->Dump(indent + 1);
449 typeAttrs.DumpAttributes();
450 LogInfo::MapleLogger() << ">";
451 }
452 }
453 #endif
454
455 #ifdef ARK_LITECG_DEBUG
Dump(int indent,bool dontUseName) const456 void MIRTypeByName::Dump(int indent, bool dontUseName) const
457 {
458 const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(nameStrIdx);
459 LogInfo::MapleLogger() << (nameIsLocal ? "<%" : "<$") << name << ">";
460 }
461 #endif
462
EqualTo(const MIRType & mirType) const463 bool MIRType::EqualTo(const MIRType &mirType) const
464 {
465 return typeKind == mirType.typeKind && primType == mirType.primType;
466 }
467
EqualTo(const MIRType & type) const468 bool MIRPtrType::EqualTo(const MIRType &type) const
469 {
470 if (typeKind != type.GetKind() || GetPrimType() != type.GetPrimType()) {
471 return false;
472 }
473 const auto &pType = static_cast<const MIRPtrType &>(type);
474 return pointedTyIdx == pType.GetPointedTyIdx() && typeAttrs == pType.GetTypeAttrs();
475 }
476
EqualTo(const MIRType & type) const477 bool MIRArrayType::EqualTo(const MIRType &type) const
478 {
479 if (type.GetKind() != typeKind) {
480 return false;
481 }
482 const auto &pType = static_cast<const MIRArrayType &>(type);
483 if (dim != pType.GetDim() || eTyIdx != pType.GetElemTyIdx() || typeAttrs != pType.GetTypeAttrs()) {
484 return false;
485 }
486 for (size_t i = 0; i < dim; ++i) {
487 if (GetSizeArrayItem(i) != pType.GetSizeArrayItem(i)) {
488 return false;
489 }
490 }
491 return true;
492 }
493
GetElemType() const494 MIRType *MIRArrayType::GetElemType() const
495 {
496 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx);
497 }
498
499 #ifdef ARK_LITECG_DEBUG
ElemNumber() const500 size_t MIRArrayType::ElemNumber() const
501 {
502 size_t elemNum = 1;
503 for (uint16 id = 0; id < dim; ++id) {
504 elemNum *= sizeArray[id];
505 }
506
507 auto elemType = GetElemType();
508 if (elemType->GetKind() == kTypeArray) {
509 elemNum *= static_cast<MIRArrayType *>(elemType)->ElemNumber();
510 }
511 return elemNum;
512 }
513 #endif
514
EqualTo(const MIRType & type) const515 bool MIRFuncType::EqualTo(const MIRType &type) const
516 {
517 if (type.GetKind() != typeKind) {
518 return false;
519 }
520 const auto &pType = static_cast<const MIRFuncType &>(type);
521 return (pType.retTyIdx == retTyIdx && pType.paramTypeList == paramTypeList && pType.funcAttrs == funcAttrs &&
522 pType.paramAttrsList == paramAttrsList && pType.retAttrs == retAttrs);
523 }
524
IsPointedTypeVolatile(int fieldID) const525 bool MIRPtrType::IsPointedTypeVolatile(int fieldID) const
526 {
527 if (typeAttrs.GetAttr(ATTR_volatile)) {
528 return true;
529 }
530 MIRType *pointedTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetPointedTyIdx());
531 return pointedTy->IsVolatile(fieldID);
532 }
533
GetSize() const534 size_t MIRPtrType::GetSize() const
535 {
536 return GetPointerSize();
537 }
GetAlign() const538 uint32 MIRPtrType::GetAlign() const
539 {
540 return GetPointerSize();
541 }
542
GetPointedFuncType() const543 MIRFuncType *MIRPtrType::GetPointedFuncType() const
544 {
545 MIRType *pointedType = GetPointedType();
546 if (pointedType->GetKind() == kTypeFunction) {
547 return static_cast<MIRFuncType *>(pointedType);
548 }
549 if (pointedType->GetKind() == kTypePointer) {
550 MIRPtrType *pointedPtrType = static_cast<MIRPtrType *>(pointedType);
551 if (pointedPtrType->GetPointedType()->GetKind() == kTypeFunction) {
552 return static_cast<MIRFuncType *>(pointedPtrType->GetPointedType());
553 }
554 }
555 return nullptr;
556 }
557 } // namespace maple
558 #endif // MIR_FEATURE_FULL
559