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_RUNTIME_PRIMITIVE_H_
18 #define ART_RUNTIME_PRIMITIVE_H_
19 
20 #include <sys/types.h>
21 
22 #include "base/logging.h"
23 #include "base/macros.h"
24 
25 namespace art {
26 
27 static constexpr size_t kObjectReferenceSize = 4;
28 
ComponentSizeShiftWidth(size_t component_size)29 constexpr 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;
34 }
35 
36 class 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,
49     kPrimLast = kPrimVoid
50   };
51 
GetType(char type)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 
ComponentSizeShift(Type type)77   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;
88       case kPrimNot:     return ComponentSizeShiftWidth(kObjectReferenceSize);
89       default:
90         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
91         return 0;
92     }
93   }
94 
ComponentSize(Type type)95   static 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       default:
108         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
109         return 0;
110     }
111   }
112 
Descriptor(Type type)113   static const char* Descriptor(Type type) {
114     switch (type) {
115       case kPrimBoolean:
116         return "Z";
117       case kPrimByte:
118         return "B";
119       case kPrimChar:
120         return "C";
121       case kPrimShort:
122         return "S";
123       case kPrimInt:
124         return "I";
125       case kPrimFloat:
126         return "F";
127       case kPrimLong:
128         return "J";
129       case kPrimDouble:
130         return "D";
131       case kPrimVoid:
132         return "V";
133       default:
134         LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
135         return nullptr;
136     }
137   }
138 
139   static const char* PrettyDescriptor(Type type);
140 
IsFloatingPointType(Type type)141   static bool IsFloatingPointType(Type type) {
142     return type == kPrimFloat || type == kPrimDouble;
143   }
144 
IsIntegralType(Type type)145   static bool IsIntegralType(Type type) {
146     // The Java language does not allow treating boolean as an integral type but
147     // our bit representation makes it safe.
148     switch (type) {
149       case kPrimBoolean:
150       case kPrimByte:
151       case kPrimChar:
152       case kPrimShort:
153       case kPrimInt:
154       case kPrimLong:
155         return true;
156       default:
157         return false;
158     }
159   }
160 
IsIntOrLongType(Type type)161   static bool IsIntOrLongType(Type type) {
162     return type == kPrimInt || type == kPrimLong;
163   }
164 
Is64BitType(Type type)165   static bool Is64BitType(Type type) {
166     return type == kPrimLong || type == kPrimDouble;
167   }
168 
169   // Return the general kind of `type`, fusing integer-like types as kPrimInt.
PrimitiveKind(Type type)170   static Type PrimitiveKind(Type type) {
171     switch (type) {
172       case kPrimBoolean:
173       case kPrimByte:
174       case kPrimShort:
175       case kPrimChar:
176       case kPrimInt:
177         return kPrimInt;
178       default:
179         return type;
180     }
181   }
182 
MinValueOfIntegralType(Type type)183   static int64_t MinValueOfIntegralType(Type type) {
184     switch (type) {
185       case kPrimBoolean:
186         return std::numeric_limits<bool>::min();
187       case kPrimByte:
188         return std::numeric_limits<int8_t>::min();
189       case kPrimChar:
190         return std::numeric_limits<uint16_t>::min();
191       case kPrimShort:
192         return std::numeric_limits<int16_t>::min();
193       case kPrimInt:
194         return std::numeric_limits<int32_t>::min();
195       case kPrimLong:
196         return std::numeric_limits<int64_t>::min();
197       default:
198         LOG(FATAL) << "non integral type";
199     }
200     return 0;
201   }
202 
MaxValueOfIntegralType(Type type)203   static int64_t MaxValueOfIntegralType(Type type) {
204     switch (type) {
205       case kPrimBoolean:
206         return std::numeric_limits<bool>::max();
207       case kPrimByte:
208         return std::numeric_limits<int8_t>::max();
209       case kPrimChar:
210         return std::numeric_limits<uint16_t>::max();
211       case kPrimShort:
212         return std::numeric_limits<int16_t>::max();
213       case kPrimInt:
214         return std::numeric_limits<int32_t>::max();
215       case kPrimLong:
216         return std::numeric_limits<int64_t>::max();
217       default:
218         LOG(FATAL) << "non integral type";
219     }
220     return 0;
221   }
222 
223  private:
224   DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
225 };
226 
227 std::ostream& operator<<(std::ostream& os, const Primitive::Type& state);
228 
229 }  // namespace art
230 
231 #endif  // ART_RUNTIME_PRIMITIVE_H_
232