1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
18 #define ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
19
20 #include <iosfwd>
21
22 #include <android-base/logging.h>
23
24 #include "base/bit_utils.h"
25
26 namespace art {
27
28 class DataType {
29 public:
30 enum class Type : uint8_t {
31 kReference = 0,
32 kBool,
33 kUint8,
34 kInt8,
35 kUint16,
36 kInt16,
37 kUint32,
38 kInt32,
39 kUint64,
40 kInt64,
41 kFloat32,
42 kFloat64,
43 kVoid,
44 kLast = kVoid
45 };
46
47 static constexpr Type FromShorty(char type);
48 static constexpr char TypeId(DataType::Type type);
49
SizeShift(Type type)50 static constexpr size_t SizeShift(Type type) {
51 switch (type) {
52 case Type::kVoid:
53 case Type::kBool:
54 case Type::kUint8:
55 case Type::kInt8:
56 return 0;
57 case Type::kUint16:
58 case Type::kInt16:
59 return 1;
60 case Type::kUint32:
61 case Type::kInt32:
62 case Type::kFloat32:
63 return 2;
64 case Type::kUint64:
65 case Type::kInt64:
66 case Type::kFloat64:
67 return 3;
68 case Type::kReference:
69 return WhichPowerOf2(kObjectReferenceSize);
70 default:
71 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
72 return 0;
73 }
74 }
75
Size(Type type)76 static constexpr size_t Size(Type type) {
77 switch (type) {
78 case Type::kVoid:
79 return 0;
80 case Type::kBool:
81 case Type::kUint8:
82 case Type::kInt8:
83 return 1;
84 case Type::kUint16:
85 case Type::kInt16:
86 return 2;
87 case Type::kUint32:
88 case Type::kInt32:
89 case Type::kFloat32:
90 return 4;
91 case Type::kUint64:
92 case Type::kInt64:
93 case Type::kFloat64:
94 return 8;
95 case Type::kReference:
96 return kObjectReferenceSize;
97 default:
98 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
99 return 0;
100 }
101 }
102
IsFloatingPointType(Type type)103 static bool IsFloatingPointType(Type type) {
104 return type == Type::kFloat32 || type == Type::kFloat64;
105 }
106
IsIntegralType(Type type)107 static bool IsIntegralType(Type type) {
108 // The Java language does not allow treating boolean as an integral type but
109 // our bit representation makes it safe.
110 switch (type) {
111 case Type::kBool:
112 case Type::kUint8:
113 case Type::kInt8:
114 case Type::kUint16:
115 case Type::kInt16:
116 case Type::kUint32:
117 case Type::kInt32:
118 case Type::kUint64:
119 case Type::kInt64:
120 return true;
121 default:
122 return false;
123 }
124 }
125
IsIntOrLongType(Type type)126 static bool IsIntOrLongType(Type type) {
127 return type == Type::kInt32 || type == Type::kInt64;
128 }
129
Is64BitType(Type type)130 static bool Is64BitType(Type type) {
131 return type == Type::kUint64 || type == Type::kInt64 || type == Type::kFloat64;
132 }
133
Is8BitType(Type type)134 static bool Is8BitType(Type type) {
135 return type == Type::kInt8 || type == Type::kUint8 || type == Type::kBool;
136 }
137
IsUnsignedType(Type type)138 static bool IsUnsignedType(Type type) {
139 return type == Type::kBool || type == Type::kUint8 || type == Type::kUint16 ||
140 type == Type::kUint32 || type == Type::kUint64;
141 }
142
143 // Return the general kind of `type`, fusing integer-like types as Type::kInt.
Kind(Type type)144 static Type Kind(Type type) {
145 switch (type) {
146 case Type::kBool:
147 case Type::kUint8:
148 case Type::kInt8:
149 case Type::kUint16:
150 case Type::kInt16:
151 case Type::kUint32:
152 case Type::kInt32:
153 return Type::kInt32;
154 case Type::kUint64:
155 case Type::kInt64:
156 return Type::kInt64;
157 default:
158 return type;
159 }
160 }
161
MinValueOfIntegralType(Type type)162 static int64_t MinValueOfIntegralType(Type type) {
163 switch (type) {
164 case Type::kBool:
165 return std::numeric_limits<bool>::min();
166 case Type::kUint8:
167 return std::numeric_limits<uint8_t>::min();
168 case Type::kInt8:
169 return std::numeric_limits<int8_t>::min();
170 case Type::kUint16:
171 return std::numeric_limits<uint16_t>::min();
172 case Type::kInt16:
173 return std::numeric_limits<int16_t>::min();
174 case Type::kUint32:
175 return std::numeric_limits<uint32_t>::min();
176 case Type::kInt32:
177 return std::numeric_limits<int32_t>::min();
178 case Type::kUint64:
179 return std::numeric_limits<uint64_t>::min();
180 case Type::kInt64:
181 return std::numeric_limits<int64_t>::min();
182 default:
183 LOG(FATAL) << "non integral type";
184 }
185 return 0;
186 }
187
MaxValueOfIntegralType(Type type)188 static int64_t MaxValueOfIntegralType(Type type) {
189 switch (type) {
190 case Type::kBool:
191 return std::numeric_limits<bool>::max();
192 case Type::kUint8:
193 return std::numeric_limits<uint8_t>::max();
194 case Type::kInt8:
195 return std::numeric_limits<int8_t>::max();
196 case Type::kUint16:
197 return std::numeric_limits<uint16_t>::max();
198 case Type::kInt16:
199 return std::numeric_limits<int16_t>::max();
200 case Type::kUint32:
201 return std::numeric_limits<uint32_t>::max();
202 case Type::kInt32:
203 return std::numeric_limits<int32_t>::max();
204 case Type::kUint64:
205 return std::numeric_limits<uint64_t>::max();
206 case Type::kInt64:
207 return std::numeric_limits<int64_t>::max();
208 default:
209 LOG(FATAL) << "non integral type";
210 }
211 return 0;
212 }
213
214 static bool IsTypeConversionImplicit(Type input_type, Type result_type);
215 static bool IsTypeConversionImplicit(int64_t value, Type result_type);
216
IsZeroExtension(Type input_type,Type result_type)217 static bool IsZeroExtension(Type input_type, Type result_type) {
218 return IsIntOrLongType(result_type) &&
219 IsUnsignedType(input_type) &&
220 Size(result_type) > Size(input_type);
221 }
222
ToSigned(Type type)223 static Type ToSigned(Type type) {
224 switch (type) {
225 case Type::kUint8:
226 return Type::kInt8;
227 case Type::kUint16:
228 return Type::kInt16;
229 case Type::kUint32:
230 return Type::kInt32;
231 case Type::kUint64:
232 return Type::kInt64;
233 default:
234 return type;
235 }
236 }
237
ToUnsigned(Type type)238 static Type ToUnsigned(Type type) {
239 switch (type) {
240 case Type::kInt8:
241 return Type::kUint8;
242 case Type::kInt16:
243 return Type::kUint16;
244 case Type::kInt32:
245 return Type::kUint32;
246 case Type::kInt64:
247 return Type::kUint64;
248 default:
249 return type;
250 }
251 }
252
253 static const char* PrettyDescriptor(Type type);
254
255 private:
256 static constexpr size_t kObjectReferenceSize = 4u;
257 };
258 std::ostream& operator<<(std::ostream& os, DataType::Type data_type);
259
260 // Defined outside DataType to have the operator<< available for DCHECK_NE().
IsTypeConversionImplicit(Type input_type,Type result_type)261 inline bool DataType::IsTypeConversionImplicit(Type input_type, Type result_type) {
262 DCHECK_NE(DataType::Type::kVoid, result_type);
263 DCHECK_NE(DataType::Type::kVoid, input_type);
264
265 // Invariant: We should never generate a conversion to a Boolean value.
266 DCHECK_NE(DataType::Type::kBool, result_type);
267
268 // Besides conversion to the same type, integral conversions to non-Int64 types
269 // are implicit if the result value range covers the input value range, i.e.
270 // widening conversions that do not need to trim the sign bits.
271 return result_type == input_type ||
272 (result_type != Type::kInt64 &&
273 IsIntegralType(input_type) &&
274 IsIntegralType(result_type) &&
275 MinValueOfIntegralType(input_type) >= MinValueOfIntegralType(result_type) &&
276 MaxValueOfIntegralType(input_type) <= MaxValueOfIntegralType(result_type));
277 }
278
IsTypeConversionImplicit(int64_t value,Type result_type)279 inline bool DataType::IsTypeConversionImplicit(int64_t value, Type result_type) {
280 if (IsIntegralType(result_type) && result_type != Type::kInt64) {
281 // If the constant value falls in the range of the result_type, type
282 // conversion isn't needed.
283 return value >= MinValueOfIntegralType(result_type) &&
284 value <= MaxValueOfIntegralType(result_type);
285 }
286 // Conversion isn't implicit if it's into non-integer types, or 64-bit int
287 // which may have different number of registers.
288 return false;
289 }
290
291 } // namespace art
292
293 #endif // ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
294