• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 namespace panda::compiler {
24 /*
25  * Type of the param/instruction
26  */
27 // NOLINTNEXTLINE(readability-identifier-naming)
28 namespace DataType {
29 enum Type : uint8_t {
30     NO_TYPE = 0,
31     REFERENCE,
32     BOOL,
33     UINT8,
34     INT8,
35     UINT16,
36     INT16,
37     UINT32,
38     INT32,
39     UINT64,
40     INT64,
41     FLOAT32,
42     FLOAT64,
43     ANY,
44     VOID,
45     POINTER,
46     LAST = POINTER
47 };
48 
49 class Any {
50 public:
Any(uint64_t value)51     explicit Any(uint64_t value) : value_(value) {}
52 
Raw()53     uint64_t Raw() const
54     {
55         return value_;
56     }
57 
58 private:
59     uint64_t value_;
60 };
61 
62 namespace internal {
63 inline constexpr std::array<const char *, Type::LAST + 1> TYPE_NAMES = {
64     "",      // NO_TYPE
65     "ref",   // REFERENCE
66     "b",     // BOOL
67     "u8",    // UINT8
68     "i8",    // INT8
69     "u16",   // UINT16
70     "i16",   // INT16
71     "u32",   // UINT32
72     "i32",   // INT32
73     "u64",   // UINT64
74     "i64",   // INT64
75     "f32",   // FLOAT32
76     "f64",   // FLOAT64
77     "any",   // ANY
78     "void",  // VOID
79     "ptr"    // POINTER
80 };
81 }  // namespace internal
82 
ToString(Type type)83 inline const char *ToString(Type type)
84 {
85     ASSERT(type <= Type::LAST);
86     return internal::TYPE_NAMES[type];
87 }
88 
GetCommonType(Type type)89 constexpr inline Type GetCommonType(Type type)
90 {
91     switch (type) {
92         case Type::BOOL:
93         case Type::UINT8:
94         case Type::INT8:
95         case Type::UINT16:
96         case Type::INT16:
97         case Type::UINT32:
98         case Type::INT32:
99         case Type::UINT64:
100         case Type::INT64:
101             return Type::INT64;
102         default:
103             return type;
104     };
105 }
106 
IsInt32Bit(Type type)107 inline bool IsInt32Bit(Type type)
108 {
109     switch (type) {
110         case Type::BOOL:
111         case Type::UINT8:
112         case Type::INT8:
113         case Type::UINT16:
114         case Type::INT16:
115         case Type::UINT32:
116         case Type::INT32:
117             return true;
118         default:
119             return false;
120     };
121 }
122 
IsTypeNumeric(Type type)123 inline bool IsTypeNumeric(Type type)
124 {
125     switch (type) {
126         case BOOL:
127         case UINT8:
128         case INT8:
129         case UINT16:
130         case INT16:
131         case UINT32:
132         case INT32:
133         case UINT64:
134         case INT64:
135         case FLOAT32:
136         case FLOAT64:
137         case POINTER:
138             return true;
139         default:
140             return false;
141     }
142 }
143 
IsLessInt32(Type type)144 inline bool IsLessInt32(Type type)
145 {
146     switch (type) {
147         case BOOL:
148         case UINT8:
149         case INT8:
150         case UINT16:
151         case INT16:
152             return true;
153         default:
154             return false;
155     }
156 }
157 
GetIntTypeForReference(Arch arch)158 inline Type GetIntTypeForReference([[maybe_unused]] Arch arch)
159 {
160     // This is necessary for arm32 cross compilation
161     if (arch == Arch::AARCH32) {
162         return UINT32;
163     }
164 
165     if constexpr (panda::OBJECT_POINTER_SIZE == sizeof(uint64_t)) {
166         return UINT64;
167     } else if constexpr (panda::OBJECT_POINTER_SIZE == sizeof(uint32_t)) {
168         return UINT32;
169     } else if constexpr (panda::OBJECT_POINTER_SIZE == sizeof(uint16_t)) {
170         UNREACHABLE_CONSTEXPR();
171         return UINT16;
172     } else {
173         UNREACHABLE_CONSTEXPR();
174         return UINT8;
175     }
176 }
177 
178 constexpr inline Type GetIntTypeBySize(size_t size_in_bytes, bool is_signed = false)
179 {
180     if (size_in_bytes <= sizeof(uint8_t)) {
181         return is_signed ? INT8 : UINT8;
182     }
183     if (size_in_bytes <= sizeof(uint16_t)) {
184         return is_signed ? INT16 : UINT16;
185     }
186     if (size_in_bytes <= sizeof(uint32_t)) {
187         return is_signed ? INT32 : UINT32;
188     }
189     if (size_in_bytes <= sizeof(uint64_t)) {
190         return is_signed ? INT64 : UINT64;
191     }
192     UNREACHABLE_CONSTEXPR();
193     return NO_TYPE;
194 }
195 
Is32Bits(Type type,Arch arch)196 inline bool Is32Bits(Type type, Arch arch)
197 {
198     switch (type) {
199         case BOOL:
200         case UINT8:
201         case INT8:
202         case UINT16:
203         case INT16:
204         case UINT32:
205         case INT32:
206         case FLOAT32:
207             return true;
208         case POINTER:
209             return !Is64BitsArch(arch);
210         case REFERENCE:
211             return Is32Bits(GetIntTypeForReference(arch), arch);
212         default:
213             return false;
214     }
215 }
216 
Is64Bits(Type type,Arch arch)217 inline bool Is64Bits(Type type, Arch arch)
218 {
219     return !Is32Bits(type, arch);
220 }
221 
IsFloatType(Type type)222 inline bool IsFloatType(Type type)
223 {
224     switch (type) {
225         case FLOAT32:
226         case FLOAT64:
227             return true;
228         default:
229             return false;
230     }
231 }
232 
IsTypeSigned(Type type)233 inline bool IsTypeSigned(Type type)
234 {
235     switch (type) {
236         case INT8:
237         case INT16:
238         case INT32:
239         case INT64:
240         case FLOAT32:
241         case FLOAT64:
242             return true;
243         default:
244             return false;
245     }
246 }
247 
IsReference(Type type)248 inline bool IsReference(Type type)
249 {
250     return type == REFERENCE;
251 }
252 
IsTypeCollectable(DataType::Type type)253 inline bool IsTypeCollectable(DataType::Type type)
254 {
255     return DataType::IsReference(type) || type == DataType::ANY;
256 }
257 
ShiftByType(Type type,Arch arch)258 inline uint8_t ShiftByType(Type type, Arch arch)
259 {
260     switch (type) {
261         case VOID:
262         case BOOL:
263         case UINT8:
264         case INT8:
265             return 0;
266         case UINT16:
267         case INT16:
268             return 1;
269         case UINT32:
270         case INT32:
271         case FLOAT32:
272             return 2U;
273         case UINT64:
274         case INT64:
275         case FLOAT64:
276         case ANY:
277             return 3U;
278         case REFERENCE:
279             return ShiftByType(GetIntTypeForReference(arch), arch);
280         case POINTER:
281             return Is64BitsArch(arch) ? 3U : 2U;
282         default:
283             UNREACHABLE();
284             return 0;
285     }
286 }
287 
GetTypeSize(Type type,Arch arch)288 inline uint8_t GetTypeSize(Type type, Arch arch)
289 {
290     // NOLINTNEXTLINE(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers)
291     return 8U << ShiftByType(type, arch);
292 }
293 }  // namespace DataType
294 }  // namespace panda::compiler
295 
296 #endif  // COMPILER_OPTIMIZER_IR_DATATYPE_H
297