• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SignedIntegralTypeFromSize(size_t size)104   static constexpr Type SignedIntegralTypeFromSize(size_t size) {
105     switch (size) {
106       case 0:
107       case 1:
108         return Type::kInt8;
109       case 2:
110         return Type::kInt16;
111       case 3:
112       case 4:
113         return Type::kInt32;
114       case 5:
115       case 6:
116       case 7:
117       case 8:
118         return Type::kInt64;
119       default:
120         LOG(FATAL) << "Invalid size " << size;
121         UNREACHABLE();
122     }
123   }
124 
IsFloatingPointType(Type type)125   static bool IsFloatingPointType(Type type) {
126     return type == Type::kFloat32 || type == Type::kFloat64;
127   }
128 
IsIntegralType(Type type)129   static bool IsIntegralType(Type type) {
130     // The Java language does not allow treating boolean as an integral type but
131     // our bit representation makes it safe.
132     switch (type) {
133       case Type::kBool:
134       case Type::kUint8:
135       case Type::kInt8:
136       case Type::kUint16:
137       case Type::kInt16:
138       case Type::kUint32:
139       case Type::kInt32:
140       case Type::kUint64:
141       case Type::kInt64:
142         return true;
143       default:
144         return false;
145     }
146   }
147 
IsIntOrLongType(Type type)148   static bool IsIntOrLongType(Type type) {
149     return type == Type::kInt32 || type == Type::kInt64;
150   }
151 
Is64BitType(Type type)152   static bool Is64BitType(Type type) {
153     return type == Type::kUint64 || type == Type::kInt64 || type == Type::kFloat64;
154   }
155 
Is8BitType(Type type)156   static bool Is8BitType(Type type) {
157     return type == Type::kInt8 || type == Type::kUint8 || type == Type::kBool;
158   }
159 
IsUnsignedType(Type type)160   static bool IsUnsignedType(Type type) {
161     return type == Type::kBool || type == Type::kUint8 || type == Type::kUint16 ||
162         type == Type::kUint32 || type == Type::kUint64;
163   }
164 
165   // Return the general kind of `type`, fusing integer-like types as Type::kInt.
Kind(Type type)166   static Type Kind(Type type) {
167     switch (type) {
168       case Type::kBool:
169       case Type::kUint8:
170       case Type::kInt8:
171       case Type::kUint16:
172       case Type::kInt16:
173       case Type::kUint32:
174       case Type::kInt32:
175         return Type::kInt32;
176       case Type::kUint64:
177       case Type::kInt64:
178         return Type::kInt64;
179       default:
180         return type;
181     }
182   }
183 
MinValueOfIntegralType(Type type)184   static int64_t MinValueOfIntegralType(Type type) {
185     switch (type) {
186       case Type::kBool:
187         return std::numeric_limits<bool>::min();
188       case Type::kUint8:
189         return std::numeric_limits<uint8_t>::min();
190       case Type::kInt8:
191         return std::numeric_limits<int8_t>::min();
192       case Type::kUint16:
193         return std::numeric_limits<uint16_t>::min();
194       case Type::kInt16:
195         return std::numeric_limits<int16_t>::min();
196       case Type::kUint32:
197         return std::numeric_limits<uint32_t>::min();
198       case Type::kInt32:
199         return std::numeric_limits<int32_t>::min();
200       case Type::kUint64:
201         return std::numeric_limits<uint64_t>::min();
202       case Type::kInt64:
203         return std::numeric_limits<int64_t>::min();
204       default:
205         LOG(FATAL) << "non integral type";
206     }
207     return 0;
208   }
209 
MaxValueOfIntegralType(Type type)210   static int64_t MaxValueOfIntegralType(Type type) {
211     switch (type) {
212       case Type::kBool:
213         return std::numeric_limits<bool>::max();
214       case Type::kUint8:
215         return std::numeric_limits<uint8_t>::max();
216       case Type::kInt8:
217         return std::numeric_limits<int8_t>::max();
218       case Type::kUint16:
219         return std::numeric_limits<uint16_t>::max();
220       case Type::kInt16:
221         return std::numeric_limits<int16_t>::max();
222       case Type::kUint32:
223         return std::numeric_limits<uint32_t>::max();
224       case Type::kInt32:
225         return std::numeric_limits<int32_t>::max();
226       case Type::kUint64:
227         return std::numeric_limits<uint64_t>::max();
228       case Type::kInt64:
229         return std::numeric_limits<int64_t>::max();
230       default:
231         LOG(FATAL) << "non integral type";
232     }
233     return 0;
234   }
235 
236   static bool IsTypeConversionImplicit(Type input_type, Type result_type);
237   static bool IsTypeConversionImplicit(int64_t value, Type result_type);
238 
IsZeroExtension(Type input_type,Type result_type)239   static bool IsZeroExtension(Type input_type, Type result_type) {
240     return IsIntOrLongType(result_type) &&
241         IsUnsignedType(input_type) &&
242         Size(result_type) > Size(input_type);
243   }
244 
ToSigned(Type type)245   static Type ToSigned(Type type) {
246     switch (type) {
247       case Type::kUint8:
248         return Type::kInt8;
249       case Type::kUint16:
250         return Type::kInt16;
251       case Type::kUint32:
252         return Type::kInt32;
253       case Type::kUint64:
254         return Type::kInt64;
255       default:
256         return type;
257     }
258   }
259 
ToUnsigned(Type type)260   static Type ToUnsigned(Type type) {
261     switch (type) {
262       case Type::kInt8:
263         return Type::kUint8;
264       case Type::kInt16:
265         return Type::kUint16;
266       case Type::kInt32:
267         return Type::kUint32;
268       case Type::kInt64:
269         return Type::kUint64;
270       default:
271         return type;
272     }
273   }
274 
275   static const char* PrettyDescriptor(Type type);
276 
277  private:
278   static constexpr size_t kObjectReferenceSize = 4u;
279 };
280 std::ostream& operator<<(std::ostream& os, DataType::Type data_type);
281 
282 // Defined outside DataType to have the operator<< available for DCHECK_NE().
IsTypeConversionImplicit(Type input_type,Type result_type)283 inline bool DataType::IsTypeConversionImplicit(Type input_type, Type result_type) {
284   DCHECK_NE(DataType::Type::kVoid, result_type);
285   DCHECK_NE(DataType::Type::kVoid, input_type);
286 
287   // Invariant: We should never generate a conversion to a Boolean value.
288   DCHECK_NE(DataType::Type::kBool, result_type);
289 
290   // Besides conversion to the same type, integral conversions to non-Int64 types
291   // are implicit if the result value range covers the input value range, i.e.
292   // widening conversions that do not need to trim the sign bits.
293   return result_type == input_type ||
294          (result_type != Type::kInt64 &&
295           IsIntegralType(input_type) &&
296           IsIntegralType(result_type) &&
297           MinValueOfIntegralType(input_type) >= MinValueOfIntegralType(result_type) &&
298           MaxValueOfIntegralType(input_type) <= MaxValueOfIntegralType(result_type));
299 }
300 
IsTypeConversionImplicit(int64_t value,Type result_type)301 inline bool DataType::IsTypeConversionImplicit(int64_t value, Type result_type) {
302   if (IsIntegralType(result_type) && result_type != Type::kInt64) {
303     // If the constant value falls in the range of the result_type, type
304     // conversion isn't needed.
305     return value >= MinValueOfIntegralType(result_type) &&
306            value <= MaxValueOfIntegralType(result_type);
307   }
308   // Conversion isn't implicit if it's into non-integer types, or 64-bit int
309   // which may have different number of registers.
310   return false;
311 }
312 
313 }  // namespace art
314 
315 #endif  // ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
316