• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mir_type.h"
17 #include "mir_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