blob: 38ad68d13db25a7a9fa9386790ed0afe757d1122 [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
Andreas Gampe57943812017-12-06 21:39:13 -080022#include <android-base/logging.h>
23
Elliott Hughes76160052012-12-12 16:31:20 -080024#include "base/macros.h"
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070025
26namespace art {
Ian Rogers68d8b422014-07-17 11:09:10 -070027
28static constexpr size_t kObjectReferenceSize = 4;
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070029
Mathieu Chartierc7853442015-03-27 14:35:38 -070030constexpr size_t ComponentSizeShiftWidth(size_t component_size) {
31 return component_size == 1u ? 0u :
32 component_size == 2u ? 1u :
33 component_size == 4u ? 2u :
34 component_size == 8u ? 3u : 0u;
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070035}
36
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070037class Primitive {
38 public:
39 enum Type {
40 kPrimNot = 0,
41 kPrimBoolean,
42 kPrimByte,
43 kPrimChar,
44 kPrimShort,
45 kPrimInt,
46 kPrimLong,
47 kPrimFloat,
48 kPrimDouble,
49 kPrimVoid,
Vladimir Markoa1de9182016-02-25 11:37:38 +000050 kPrimLast = kPrimVoid
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070051 };
52
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010053 static constexpr Type GetType(char type) {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070054 switch (type) {
55 case 'B':
56 return kPrimByte;
57 case 'C':
58 return kPrimChar;
59 case 'D':
60 return kPrimDouble;
61 case 'F':
62 return kPrimFloat;
63 case 'I':
64 return kPrimInt;
65 case 'J':
66 return kPrimLong;
67 case 'S':
68 return kPrimShort;
69 case 'Z':
70 return kPrimBoolean;
71 case 'V':
72 return kPrimVoid;
73 default:
74 return kPrimNot;
75 }
76 }
77
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010078 static constexpr size_t ComponentSizeShift(Type type) {
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070079 switch (type) {
80 case kPrimVoid:
81 case kPrimBoolean:
82 case kPrimByte: return 0;
83 case kPrimChar:
84 case kPrimShort: return 1;
85 case kPrimInt:
86 case kPrimFloat: return 2;
87 case kPrimLong:
88 case kPrimDouble: return 3;
Mathieu Chartierc7853442015-03-27 14:35:38 -070089 case kPrimNot: return ComponentSizeShiftWidth(kObjectReferenceSize);
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070090 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010091 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
92 UNREACHABLE();
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070093 }
94
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010095 static constexpr size_t ComponentSize(Type type) {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -070096 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 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100108 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
109 UNREACHABLE();
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700110 }
111
Elliott Hughes91250e02011-12-13 22:30:35 -0800112 static const char* Descriptor(Type type) {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700113 switch (type) {
114 case kPrimBoolean:
Elliott Hughes91250e02011-12-13 22:30:35 -0800115 return "Z";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700116 case kPrimByte:
Elliott Hughes91250e02011-12-13 22:30:35 -0800117 return "B";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700118 case kPrimChar:
Elliott Hughes91250e02011-12-13 22:30:35 -0800119 return "C";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700120 case kPrimShort:
Elliott Hughes91250e02011-12-13 22:30:35 -0800121 return "S";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700122 case kPrimInt:
Elliott Hughes91250e02011-12-13 22:30:35 -0800123 return "I";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700124 case kPrimFloat:
Elliott Hughes91250e02011-12-13 22:30:35 -0800125 return "F";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700126 case kPrimLong:
Elliott Hughes91250e02011-12-13 22:30:35 -0800127 return "J";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700128 case kPrimDouble:
Elliott Hughes91250e02011-12-13 22:30:35 -0800129 return "D";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800130 case kPrimVoid:
Elliott Hughes91250e02011-12-13 22:30:35 -0800131 return "V";
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700132 default:
133 LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700134 return nullptr;
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700135 }
136 }
137
Roland Levillain5c4405e2015-01-21 11:39:58 +0000138 static const char* PrettyDescriptor(Type type);
139
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000140 // Returns the descriptor corresponding to the boxed type of |type|.
141 static const char* BoxedDescriptor(Type type);
142
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000143 // Returns true if |type| is an numeric type.
Orion Hodsonf1412b42016-11-11 12:03:29 +0000144 static constexpr bool IsNumericType(Type type) {
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000145 switch (type) {
146 case Primitive::Type::kPrimNot: return false;
147 case Primitive::Type::kPrimBoolean: return false;
148 case Primitive::Type::kPrimByte: return true;
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000149 case Primitive::Type::kPrimChar: return true;
150 case Primitive::Type::kPrimShort: return true;
151 case Primitive::Type::kPrimInt: return true;
152 case Primitive::Type::kPrimLong: return true;
153 case Primitive::Type::kPrimFloat: return true;
154 case Primitive::Type::kPrimDouble: return true;
155 case Primitive::Type::kPrimVoid: return false;
156 }
157 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
158 UNREACHABLE();
159 }
160
161 // Return trues if |type| is a signed numeric type.
162 static constexpr bool IsSignedNumericType(Type type) {
163 switch (type) {
164 case Primitive::Type::kPrimNot: return false;
165 case Primitive::Type::kPrimBoolean: return false;
166 case Primitive::Type::kPrimByte: return true;
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000167 case Primitive::Type::kPrimChar: return false;
168 case Primitive::Type::kPrimShort: return true;
169 case Primitive::Type::kPrimInt: return true;
170 case Primitive::Type::kPrimLong: return true;
171 case Primitive::Type::kPrimFloat: return true;
172 case Primitive::Type::kPrimDouble: return true;
173 case Primitive::Type::kPrimVoid: return false;
174 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100175 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
176 UNREACHABLE();
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000177 }
178
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000179 // Returns the number of bits required to hold the largest
180 // positive number that can be represented by |type|.
181 static constexpr size_t BitsRequiredForLargestValue(Type type) {
182 switch (type) {
183 case Primitive::Type::kPrimNot: return 0u;
184 case Primitive::Type::kPrimBoolean: return 1u;
185 case Primitive::Type::kPrimByte: return 7u;
186 case Primitive::Type::kPrimChar: return 16u;
187 case Primitive::Type::kPrimShort: return 15u;
188 case Primitive::Type::kPrimInt: return 31u;
189 case Primitive::Type::kPrimLong: return 63u;
190 case Primitive::Type::kPrimFloat: return 128u;
191 case Primitive::Type::kPrimDouble: return 1024u;
192 case Primitive::Type::kPrimVoid: return 0u;
193 }
194 }
195
Orion Hodsonf1412b42016-11-11 12:03:29 +0000196 // Returns true if it is possible to widen type |from| to type |to|. Both |from| and
197 // |to| should be numeric primitive types.
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000198 static bool IsWidenable(Type from, Type to) {
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000199 if (!IsNumericType(from) || !IsNumericType(to)) {
200 // Widening is only applicable between numeric types.
201 return false;
202 }
203 if (IsSignedNumericType(from) && !IsSignedNumericType(to)) {
204 // Nowhere to store the sign bit in |to|.
205 return false;
206 }
207 if (BitsRequiredForLargestValue(from) > BitsRequiredForLargestValue(to)) {
208 // The from,to pair corresponds to a narrowing.
209 return false;
210 }
211 return true;
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000212 }
213
Alexandre Rames542361f2015-01-29 16:57:31 +0000214 static bool Is64BitType(Type type) {
215 return type == kPrimLong || type == kPrimDouble;
216 }
217
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700218 private:
219 DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
220};
221
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100222std::ostream& operator<<(std::ostream& os, Primitive::Type state);
Brian Carlstromae826982011-11-09 01:33:42 -0800223
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700224} // namespace art
225
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700226#endif // ART_RUNTIME_PRIMITIVE_H_