• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMPILER_OPTIMIZER_IR_DATATYPE_H
17 #define COMPILER_OPTIMIZER_IR_DATATYPE_H
18 
19 #include "macros.h"
20 #include "utils/arch.h"
21 #include "mem/mem.h"
22 
23 // NOLINTNEXTLINE(modernize-concat-nested-namespaces)
24 namespace ark::compiler {
25 /*
26  * Type of the param/instruction
27  */
28 // NOLINTNEXTLINE(readability-identifier-naming)
29 namespace DataType {
30 enum Type : uint8_t {
31     NO_TYPE = 0,
32     REFERENCE,
33     BOOL,
34     UINT8,
35     INT8,
36     UINT16,
37     INT16,
38     UINT32,
39     INT32,
40     UINT64,
41     INT64,
42     FLOAT32,
43     FLOAT64,
44     ANY,
45     VOID,
46     POINTER,
47     LAST = POINTER
48 };
49 
50 class Any {
51 public:
Any(uint64_t value)52     explicit Any(uint64_t value) : value_(value) {}
53 
Raw()54     uint64_t Raw() const
55     {
56         return value_;
57     }
58 
59 private:
60     uint64_t value_ {0};
61 };
62 
63 namespace internal {
64 inline constexpr std::array<const char *, Type::LAST + 1> TYPE_NAMES = {
65     "",      // NO_TYPE
66     "ref",   // REFERENCE
67     "b",     // BOOL
68     "u8",    // UINT8
69     "i8",    // INT8
70     "u16",   // UINT16
71     "i16",   // INT16
72     "u32",   // UINT32
73     "i32",   // INT32
74     "u64",   // UINT64
75     "i64",   // INT64
76     "f32",   // FLOAT32
77     "f64",   // FLOAT64
78     "any",   // ANY
79     "void",  // VOID
80     "ptr"    // POINTER
81 };
82 }  // namespace internal
83 
ToString(Type type)84 inline const char *ToString(Type type)
85 {
86     ASSERT(type <= Type::LAST);
87     return internal::TYPE_NAMES[type];
88 }
89 
90 inline std::ostream &operator<<(std::ostream &os, const DataType::Type &type)
91 {
92     os << ToString(type);
93     return os;
94 }
95 
96 // CC-OFFNXT(G.FUD.06) switch-case, ODR
GetCommonType(Type type)97 constexpr inline Type GetCommonType(Type type)
98 {
99     switch (type) {
100         case Type::BOOL:
101         case Type::UINT8:
102         case Type::INT8:
103         case Type::UINT16:
104         case Type::INT16:
105         case Type::UINT32:
106         case Type::INT32:
107         case Type::UINT64:
108         case Type::INT64:
109             return Type::INT64;
110         case Type::REFERENCE:
111         case Type::POINTER:
112             return Type::POINTER;
113         default:
114             return type;
115     };
116 }
117 
118 // CC-OFFNXT(G.FUD.06) switch-case, ODR
IsInt32Bit(Type type)119 inline bool IsInt32Bit(Type type)
120 {
121     switch (type) {
122         case Type::BOOL:
123         case Type::UINT8:
124         case Type::INT8:
125         case Type::UINT16:
126         case Type::INT16:
127         case Type::UINT32:
128         case Type::INT32:
129             return true;
130         default:
131             return false;
132     };
133 }
134 
135 // CC-OFFNXT(G.FUD.06) switch-case, ODR
IsTypeNumeric(Type type)136 inline bool IsTypeNumeric(Type type)
137 {
138     switch (type) {
139         case BOOL:
140         case UINT8:
141         case INT8:
142         case UINT16:
143         case INT16:
144         case UINT32:
145         case INT32:
146         case UINT64:
147         case INT64:
148         case FLOAT32:
149         case FLOAT64:
150         case POINTER:
151             return true;
152         default:
153             return false;
154     }
155 }
156 
IsLessInt32(Type type)157 inline bool IsLessInt32(Type type)
158 {
159     switch (type) {
160         case BOOL:
161         case UINT8:
162         case INT8:
163         case UINT16:
164         case INT16:
165             return true;
166         default:
167             return false;
168     }
169 }
170 
171 // CC-OFFNXT(G.FUD.06) switch-case, ODR
GetIntTypeForReference(Arch arch)172 inline Type GetIntTypeForReference([[maybe_unused]] Arch arch)
173 {
174     // This is necessary for arm32 cross compilation
175     if (arch == Arch::AARCH32) {
176         return UINT32;
177     }
178 
179     if constexpr (ark::OBJECT_POINTER_SIZE == sizeof(uint64_t)) {
180         return UINT64;
181     } else if constexpr (ark::OBJECT_POINTER_SIZE == sizeof(uint32_t)) {
182         return UINT32;
183     } else if constexpr (ark::OBJECT_POINTER_SIZE == sizeof(uint16_t)) {
184         UNREACHABLE_CONSTEXPR();
185         return UINT16;
186     } else {
187         UNREACHABLE_CONSTEXPR();
188         return UINT8;
189     }
190 }
191 
192 // CC-OFFNXT(G.FUD.06) switch-case, ODR
193 constexpr inline Type GetIntTypeBySize(size_t sizeInBytes, bool isSigned = false)
194 {
195     if (sizeInBytes <= sizeof(uint8_t)) {
196         return isSigned ? INT8 : UINT8;
197     }
198     if (sizeInBytes <= sizeof(uint16_t)) {
199         return isSigned ? INT16 : UINT16;
200     }
201     if (sizeInBytes <= sizeof(uint32_t)) {
202         return isSigned ? INT32 : UINT32;
203     }
204     if (sizeInBytes <= sizeof(uint64_t)) {
205         return isSigned ? INT64 : UINT64;
206     }
207     UNREACHABLE_CONSTEXPR();
208     return NO_TYPE;
209 }
210 
211 // CC-OFFNXT(G.FUD.06) switch-case, ODR
Is32Bits(Type type,Arch arch)212 inline bool Is32Bits(Type type, Arch arch)
213 {
214     switch (type) {
215         case BOOL:
216         case UINT8:
217         case INT8:
218         case UINT16:
219         case INT16:
220         case UINT32:
221         case INT32:
222         case FLOAT32:
223             return true;
224         case POINTER:
225             return !Is64BitsArch(arch);
226         case REFERENCE:
227             return Is32Bits(GetIntTypeForReference(arch), arch);
228         default:
229             return false;
230     }
231 }
232 
Is64Bits(Type type,Arch arch)233 inline bool Is64Bits(Type type, Arch arch)
234 {
235     return !Is32Bits(type, arch);
236 }
237 
IsFloatType(Type type)238 inline bool IsFloatType(Type type)
239 {
240     switch (type) {
241         case FLOAT32:
242         case FLOAT64:
243             return true;
244         default:
245             return false;
246     }
247 }
248 
249 // CC-OFFNXT(G.FUD.06) switch-case, ODR
IsTypeSigned(Type type)250 inline bool IsTypeSigned(Type type)
251 {
252     switch (type) {
253         case INT8:
254         case INT16:
255         case INT32:
256         case INT64:
257         case FLOAT32:
258         case FLOAT64:
259             return true;
260         default:
261             return false;
262     }
263 }
264 
IsReference(Type type)265 inline bool IsReference(Type type)
266 {
267     return type == REFERENCE;
268 }
269 
270 // CC-OFFNXT(G.FUD.06) switch-case, ODR
ShiftByType(Type type,Arch arch)271 inline uint8_t ShiftByType(Type type, Arch arch)
272 {
273     switch (type) {
274         case VOID:
275         case BOOL:
276         case UINT8:
277         case INT8:
278             return 0;
279         case UINT16:
280         case INT16:
281             return 1;
282         case UINT32:
283         case INT32:
284         case FLOAT32:
285             return 2U;
286         case UINT64:
287         case INT64:
288         case FLOAT64:
289         case ANY:
290             return 3U;
291         case REFERENCE:
292             return ShiftByType(GetIntTypeForReference(arch), arch);
293         case POINTER:
294             return Is64BitsArch(arch) ? 3U : 2U;
295         default:
296             UNREACHABLE();
297             return 0;
298     }
299 }
300 
GetTypeSize(Type type,Arch arch)301 inline uint8_t GetTypeSize(Type type, Arch arch)
302 {
303     // NOLINTNEXTLINE(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers)
304     return 8U << ShiftByType(type, arch);
305 }
306 
GetTypeByteSize(Type type,Arch arch)307 inline uint8_t GetTypeByteSize(Type type, Arch arch)
308 {
309     // NOLINTNEXTLINE(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers)
310     return 1U << ShiftByType(type, arch);
311 }
312 
NeedCastIntTypes(Arch arch,DataType::Type typeBefore,DataType::Type typeAfter)313 inline bool NeedCastIntTypes(Arch arch, DataType::Type typeBefore, DataType::Type typeAfter)
314 {
315     auto sizeBefore = DataType::GetTypeSize(typeBefore, arch);
316     auto sizeAfter = DataType::GetTypeSize(typeAfter, arch);
317 
318     // In our ISA minimal type is 32-bit, so type less then 32-bit we should extend to 32-bit.
319     // Thereby we may to avoid some casts.
320     constexpr auto NUM_BITS_INT32 = 32U;
321     bool extendNotNeed = sizeBefore < sizeAfter && sizeAfter <= NUM_BITS_INT32;
322     return !extendNotNeed || DataType::IsTypeSigned(typeBefore) != DataType::IsTypeSigned(typeAfter);
323 }
324 
NeedCastForTypes(Arch arch,DataType::Type typeBefore,DataType::Type typeAfter)325 inline bool NeedCastForTypes(Arch arch, DataType::Type typeBefore, DataType::Type typeAfter)
326 {
327     // If types is equal, we avoid cast
328     if (typeBefore == typeAfter) {
329         return false;
330     }
331 
332     // There are types left here: int and float
333     ASSERT(DataType::IsTypeNumeric(typeBefore) && DataType::IsTypeNumeric(typeAfter));
334     if (DataType::IsFloatType(typeBefore) || DataType::IsFloatType(typeAfter)) {
335         return true;
336     }
337 
338     // There are types left here: int
339     return NeedCastIntTypes(arch, typeBefore, typeAfter);
340 }
341 
342 }  // namespace DataType
343 }  // namespace ark::compiler
344 
345 #endif  // COMPILER_OPTIMIZER_IR_DATATYPE_H
346