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