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