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
25namespace art {
26
27static constexpr size_t kObjectReferenceSize = 4;
28
29constexpr 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
36class 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
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
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
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
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
141  static bool IsFloatingPointType(Type type) {
142    return type == kPrimFloat || type == kPrimDouble;
143  }
144
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
161  static bool IsIntOrLongType(Type type) {
162    return type == kPrimInt || type == kPrimLong;
163  }
164
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.
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
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
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
227std::ostream& operator<<(std::ostream& os, const Primitive::Type& state);
228
229}  // namespace art
230
231#endif  // ART_RUNTIME_PRIMITIVE_H_
232