blob: 7cc47ad79b262aff3cf32319bc63632a9576aed2 [file] [log] [blame]
Brian Carlstrom6b4ef022011-10-23 14:59:04 -07001/*
2 * Copyright (C) 2011 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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_PRIMITIVE_H_
18#define ART_RUNTIME_PRIMITIVE_H_
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070019
20#include <sys/types.h>
21
Elliott Hughes07ed66b2012-12-12 18:34:25 -080022#include "base/logging.h"
Elliott Hughes76160052012-12-12 16:31:20 -080023#include "base/macros.h"
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070024
25namespace art {
Ian Rogers68d8b422014-07-17 11:09:10 -070026
27static constexpr size_t kObjectReferenceSize = 4;
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070028
Mathieu Chartierc7853442015-03-27 14:35:38 -070029constexpr size_t ComponentSizeShiftWidth(size_t component_size) {
30 return component_size == 1u ? 0u :
31 component_size == 2u ? 1u :
32 component_size == 4u ? 2u :
33 component_size == 8u ? 3u : 0u;
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070034}
35
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070036class Primitive {
37 public:
38 enum Type {
39 kPrimNot = 0,
40 kPrimBoolean,
41 kPrimByte,
42 kPrimChar,
43 kPrimShort,
44 kPrimInt,
45 kPrimLong,
46 kPrimFloat,
47 kPrimDouble,
48 kPrimVoid,
Vladimir Markoa1de9182016-02-25 11:37:38 +000049 kPrimLast = kPrimVoid
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070050 };
51
52 static Type GetType(char type) {
53 switch (type) {
54 case 'B':
55 return kPrimByte;
56 case 'C':
57 return kPrimChar;
58 case 'D':
59 return kPrimDouble;
60 case 'F':
61 return kPrimFloat;
62 case 'I':
63 return kPrimInt;
64 case 'J':
65 return kPrimLong;
66 case 'S':
67 return kPrimShort;
68 case 'Z':
69 return kPrimBoolean;
70 case 'V':
71 return kPrimVoid;
72 default:
73 return kPrimNot;
74 }
75 }
76
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070077 static size_t ComponentSizeShift(Type type) {
78 switch (type) {
79 case kPrimVoid:
80 case kPrimBoolean:
81 case kPrimByte: return 0;
82 case kPrimChar:
83 case kPrimShort: return 1;
84 case kPrimInt:
85 case kPrimFloat: return 2;
86 case kPrimLong:
87 case kPrimDouble: return 3;
Mathieu Chartierc7853442015-03-27 14:35:38 -070088 case kPrimNot: return ComponentSizeShiftWidth(kObjectReferenceSize);
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070089 default:
90 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
91 return 0;
92 }
93 }
94
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070095 static size_t ComponentSize(Type type) {
96 switch (type) {
Ian Rogers169c9a72011-11-13 20:13:17 -080097 case kPrimVoid: return 0;
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070098 case kPrimBoolean:
99 case kPrimByte: return 1;
100 case kPrimChar:
101 case kPrimShort: return 2;
102 case kPrimInt:
103 case kPrimFloat: return 4;
104 case kPrimLong:
105 case kPrimDouble: return 8;
Ian Rogers68d8b422014-07-17 11:09:10 -0700106 case kPrimNot: return kObjectReferenceSize;
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700107 default:
108 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
109 return 0;
110 }
111 }
112
Elliott Hughes91250e02011-12-13 22:30:35 -0800113 static const char* Descriptor(Type type) {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700114 switch (type) {
115 case kPrimBoolean:
Elliott Hughes91250e02011-12-13 22:30:35 -0800116 return "Z";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700117 case kPrimByte:
Elliott Hughes91250e02011-12-13 22:30:35 -0800118 return "B";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700119 case kPrimChar:
Elliott Hughes91250e02011-12-13 22:30:35 -0800120 return "C";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700121 case kPrimShort:
Elliott Hughes91250e02011-12-13 22:30:35 -0800122 return "S";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700123 case kPrimInt:
Elliott Hughes91250e02011-12-13 22:30:35 -0800124 return "I";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700125 case kPrimFloat:
Elliott Hughes91250e02011-12-13 22:30:35 -0800126 return "F";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700127 case kPrimLong:
Elliott Hughes91250e02011-12-13 22:30:35 -0800128 return "J";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700129 case kPrimDouble:
Elliott Hughes91250e02011-12-13 22:30:35 -0800130 return "D";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800131 case kPrimVoid:
Elliott Hughes91250e02011-12-13 22:30:35 -0800132 return "V";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700133 default:
134 LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700135 return nullptr;
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700136 }
137 }
138
Roland Levillain5c4405e2015-01-21 11:39:58 +0000139 static const char* PrettyDescriptor(Type type);
140
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000141 // Returns the descriptor corresponding to the boxed type of |type|.
142 static const char* BoxedDescriptor(Type type);
143
Alexandre Rames542361f2015-01-29 16:57:31 +0000144 static bool IsFloatingPointType(Type type) {
145 return type == kPrimFloat || type == kPrimDouble;
146 }
147
148 static bool IsIntegralType(Type type) {
David Brazdilb2bd1c52015-03-25 11:17:37 +0000149 // The Java language does not allow treating boolean as an integral type but
150 // our bit representation makes it safe.
Alexandre Rames542361f2015-01-29 16:57:31 +0000151 switch (type) {
David Brazdil46e2a392015-03-16 17:31:52 +0000152 case kPrimBoolean:
Alexandre Rames542361f2015-01-29 16:57:31 +0000153 case kPrimByte:
154 case kPrimChar:
155 case kPrimShort:
156 case kPrimInt:
157 case kPrimLong:
158 return true;
159 default:
160 return false;
161 }
162 }
163
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000164 // Return true if |type| is an numeric type.
165 static bool IsNumericType(Type type) {
166 switch (type) {
167 case Primitive::Type::kPrimNot: return false;
168 case Primitive::Type::kPrimBoolean: return false;
169 case Primitive::Type::kPrimByte: return true;
170 case Primitive::Type::kPrimChar: return false;
171 case Primitive::Type::kPrimShort: return true;
172 case Primitive::Type::kPrimInt: return true;
173 case Primitive::Type::kPrimLong: return true;
174 case Primitive::Type::kPrimFloat: return true;
175 case Primitive::Type::kPrimDouble: return true;
176 case Primitive::Type::kPrimVoid: return false;
177 }
178 }
179
180 // Returns true if |from| and |to| are the same or a widening conversion exists between them.
181 static bool IsWidenable(Type from, Type to) {
182 static_assert(Primitive::Type::kPrimByte < Primitive::Type::kPrimShort, "Bad ordering");
183 static_assert(Primitive::Type::kPrimShort < Primitive::Type::kPrimInt, "Bad ordering");
184 static_assert(Primitive::Type::kPrimInt < Primitive::Type::kPrimLong, "Bad ordering");
185 static_assert(Primitive::Type::kPrimLong < Primitive::Type::kPrimFloat, "Bad ordering");
186 static_assert(Primitive::Type::kPrimFloat < Primitive::Type::kPrimDouble, "Bad ordering");
187 return IsNumericType(from) && IsNumericType(to) && from <= to;
188 }
189
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +0000190 static bool IsIntOrLongType(Type type) {
191 return type == kPrimInt || type == kPrimLong;
192 }
193
Alexandre Rames542361f2015-01-29 16:57:31 +0000194 static bool Is64BitType(Type type) {
195 return type == kPrimLong || type == kPrimDouble;
196 }
197
Roland Levillaina5c4a402016-03-15 15:02:50 +0000198 // Return the general kind of `type`, fusing integer-like types as kPrimInt.
199 static Type PrimitiveKind(Type type) {
200 switch (type) {
201 case kPrimBoolean:
202 case kPrimByte:
203 case kPrimShort:
204 case kPrimChar:
205 case kPrimInt:
206 return kPrimInt;
207 default:
208 return type;
209 }
210 }
211
Aart Bik0d345cf2016-03-16 10:49:38 -0700212 static int64_t MinValueOfIntegralType(Type type) {
213 switch (type) {
214 case kPrimBoolean:
215 return std::numeric_limits<bool>::min();
216 case kPrimByte:
217 return std::numeric_limits<int8_t>::min();
218 case kPrimChar:
219 return std::numeric_limits<uint16_t>::min();
220 case kPrimShort:
221 return std::numeric_limits<int16_t>::min();
222 case kPrimInt:
223 return std::numeric_limits<int32_t>::min();
224 case kPrimLong:
225 return std::numeric_limits<int64_t>::min();
226 default:
227 LOG(FATAL) << "non integral type";
228 }
229 return 0;
230 }
231
232 static int64_t MaxValueOfIntegralType(Type type) {
233 switch (type) {
234 case kPrimBoolean:
235 return std::numeric_limits<bool>::max();
236 case kPrimByte:
237 return std::numeric_limits<int8_t>::max();
238 case kPrimChar:
239 return std::numeric_limits<uint16_t>::max();
240 case kPrimShort:
241 return std::numeric_limits<int16_t>::max();
242 case kPrimInt:
243 return std::numeric_limits<int32_t>::max();
244 case kPrimLong:
245 return std::numeric_limits<int64_t>::max();
246 default:
247 LOG(FATAL) << "non integral type";
248 }
249 return 0;
250 }
251
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700252 private:
253 DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
254};
255
Brian Carlstromae826982011-11-09 01:33:42 -0800256std::ostream& operator<<(std::ostream& os, const Primitive::Type& state);
257
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700258} // namespace art
259
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700260#endif // ART_RUNTIME_PRIMITIVE_H_