• 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 
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