1 /*
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
17 #ifndef ART_LIBDEXFILE_DEX_PRIMITIVE_H_
18 #define ART_LIBDEXFILE_DEX_PRIMITIVE_H_
19
20 #include <sys/types.h>
21
22 #include <android-base/logging.h>
23
24 #include "base/macros.h"
25
26 namespace art {
27
28 static constexpr size_t kObjectReferenceSize = 4;
29
ComponentSizeShiftWidth(size_t component_size)30 constexpr 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;
35 }
36
37 class 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,
50 kPrimLast = kPrimVoid
51 };
52
GetType(char type)53 static constexpr Type GetType(char type) {
54 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
ComponentSizeShift(Type type)78 static constexpr size_t ComponentSizeShift(Type type) {
79 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;
89 case kPrimNot: return ComponentSizeShiftWidth(kObjectReferenceSize);
90 }
91 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
92 UNREACHABLE();
93 }
94
ComponentSize(Type type)95 static constexpr size_t ComponentSize(Type type) {
96 switch (type) {
97 case kPrimVoid: return 0;
98 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;
106 case kPrimNot: return kObjectReferenceSize;
107 }
108 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
109 UNREACHABLE();
110 }
111
Descriptor(Type type)112 static const char* Descriptor(Type type) {
113 switch (type) {
114 case kPrimBoolean:
115 return "Z";
116 case kPrimByte:
117 return "B";
118 case kPrimChar:
119 return "C";
120 case kPrimShort:
121 return "S";
122 case kPrimInt:
123 return "I";
124 case kPrimFloat:
125 return "F";
126 case kPrimLong:
127 return "J";
128 case kPrimDouble:
129 return "D";
130 case kPrimVoid:
131 return "V";
132 default:
133 LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
134 return nullptr;
135 }
136 }
137
138 static const char* PrettyDescriptor(Type type);
139
140 // Returns the descriptor corresponding to the boxed type of |type|.
141 static const char* BoxedDescriptor(Type type);
142
143 // Returns true if |type| is an numeric type.
IsNumericType(Type type)144 static constexpr bool IsNumericType(Type type) {
145 switch (type) {
146 case Primitive::Type::kPrimNot: return false;
147 case Primitive::Type::kPrimBoolean: return false;
148 case Primitive::Type::kPrimByte: return true;
149 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.
IsSignedNumericType(Type 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;
167 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 }
175 LOG(FATAL) << "Invalid type " << static_cast<int>(type);
176 UNREACHABLE();
177 }
178
179 // Returns the number of bits required to hold the largest
180 // positive number that can be represented by |type|.
BitsRequiredForLargestValue(Type 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
196 // Returns true if it is possible to widen type |from| to type |to|. Both |from| and
197 // |to| should be numeric primitive types.
IsWidenable(Type from,Type to)198 static bool IsWidenable(Type from, Type to) {
199 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;
212 }
213
Is64BitType(Type type)214 static bool Is64BitType(Type type) {
215 return type == kPrimLong || type == kPrimDouble;
216 }
217
218 private:
219 DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
220 };
221
222 std::ostream& operator<<(std::ostream& os, Primitive::Type state);
223
224 } // namespace art
225
226 #endif // ART_LIBDEXFILE_DEX_PRIMITIVE_H_
227