1 /* 2 * Copyright (C) 2017 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_COMPILER_OPTIMIZING_DATA_TYPE_H_ 18 #define ART_COMPILER_OPTIMIZING_DATA_TYPE_H_ 19 20 #include <iosfwd> 21 22 #include <android-base/logging.h> 23 24 #include "base/bit_utils.h" 25 26 namespace art { 27 28 class DataType { 29 public: 30 enum class Type : uint8_t { 31 kReference = 0, 32 kBool, 33 kUint8, 34 kInt8, 35 kUint16, 36 kInt16, 37 kUint32, 38 kInt32, 39 kUint64, 40 kInt64, 41 kFloat32, 42 kFloat64, 43 kVoid, 44 kLast = kVoid 45 }; 46 47 static constexpr Type FromShorty(char type); 48 static constexpr char TypeId(DataType::Type type); 49 50 static constexpr size_t SizeShift(Type type) { 51 switch (type) { 52 case Type::kVoid: 53 case Type::kBool: 54 case Type::kUint8: 55 case Type::kInt8: 56 return 0; 57 case Type::kUint16: 58 case Type::kInt16: 59 return 1; 60 case Type::kUint32: 61 case Type::kInt32: 62 case Type::kFloat32: 63 return 2; 64 case Type::kUint64: 65 case Type::kInt64: 66 case Type::kFloat64: 67 return 3; 68 case Type::kReference: 69 return WhichPowerOf2(kObjectReferenceSize); 70 default: 71 LOG(FATAL) << "Invalid type " << static_cast<int>(type); 72 return 0; 73 } 74 } 75 76 static constexpr size_t Size(Type type) { 77 switch (type) { 78 case Type::kVoid: 79 return 0; 80 case Type::kBool: 81 case Type::kUint8: 82 case Type::kInt8: 83 return 1; 84 case Type::kUint16: 85 case Type::kInt16: 86 return 2; 87 case Type::kUint32: 88 case Type::kInt32: 89 case Type::kFloat32: 90 return 4; 91 case Type::kUint64: 92 case Type::kInt64: 93 case Type::kFloat64: 94 return 8; 95 case Type::kReference: 96 return kObjectReferenceSize; 97 default: 98 LOG(FATAL) << "Invalid type " << static_cast<int>(type); 99 return 0; 100 } 101 } 102 103 static bool IsFloatingPointType(Type type) { 104 return type == Type::kFloat32 || type == Type::kFloat64; 105 } 106 107 static bool IsIntegralType(Type type) { 108 // The Java language does not allow treating boolean as an integral type but 109 // our bit representation makes it safe. 110 switch (type) { 111 case Type::kBool: 112 case Type::kUint8: 113 case Type::kInt8: 114 case Type::kUint16: 115 case Type::kInt16: 116 case Type::kUint32: 117 case Type::kInt32: 118 case Type::kUint64: 119 case Type::kInt64: 120 return true; 121 default: 122 return false; 123 } 124 } 125 126 static bool IsIntOrLongType(Type type) { 127 return type == Type::kInt32 || type == Type::kInt64; 128 } 129 130 static bool Is64BitType(Type type) { 131 return type == Type::kUint64 || type == Type::kInt64 || type == Type::kFloat64; 132 } 133 134 static bool IsUnsignedType(Type type) { 135 return type == Type::kBool || type == Type::kUint8 || type == Type::kUint16 || 136 type == Type::kUint32 || type == Type::kUint64; 137 } 138 139 // Return the general kind of `type`, fusing integer-like types as Type::kInt. 140 static Type Kind(Type type) { 141 switch (type) { 142 case Type::kBool: 143 case Type::kUint8: 144 case Type::kInt8: 145 case Type::kUint16: 146 case Type::kInt16: 147 case Type::kUint32: 148 case Type::kInt32: 149 return Type::kInt32; 150 case Type::kUint64: 151 case Type::kInt64: 152 return Type::kInt64; 153 default: 154 return type; 155 } 156 } 157 158 static int64_t MinValueOfIntegralType(Type type) { 159 switch (type) { 160 case Type::kBool: 161 return std::numeric_limits<bool>::min(); 162 case Type::kUint8: 163 return std::numeric_limits<uint8_t>::min(); 164 case Type::kInt8: 165 return std::numeric_limits<int8_t>::min(); 166 case Type::kUint16: 167 return std::numeric_limits<uint16_t>::min(); 168 case Type::kInt16: 169 return std::numeric_limits<int16_t>::min(); 170 case Type::kUint32: 171 return std::numeric_limits<uint32_t>::min(); 172 case Type::kInt32: 173 return std::numeric_limits<int32_t>::min(); 174 case Type::kUint64: 175 return std::numeric_limits<uint64_t>::min(); 176 case Type::kInt64: 177 return std::numeric_limits<int64_t>::min(); 178 default: 179 LOG(FATAL) << "non integral type"; 180 } 181 return 0; 182 } 183 184 static int64_t MaxValueOfIntegralType(Type type) { 185 switch (type) { 186 case Type::kBool: 187 return std::numeric_limits<bool>::max(); 188 case Type::kUint8: 189 return std::numeric_limits<uint8_t>::max(); 190 case Type::kInt8: 191 return std::numeric_limits<int8_t>::max(); 192 case Type::kUint16: 193 return std::numeric_limits<uint16_t>::max(); 194 case Type::kInt16: 195 return std::numeric_limits<int16_t>::max(); 196 case Type::kUint32: 197 return std::numeric_limits<uint32_t>::max(); 198 case Type::kInt32: 199 return std::numeric_limits<int32_t>::max(); 200 case Type::kUint64: 201 return std::numeric_limits<uint64_t>::max(); 202 case Type::kInt64: 203 return std::numeric_limits<int64_t>::max(); 204 default: 205 LOG(FATAL) << "non integral type"; 206 } 207 return 0; 208 } 209 210 static bool IsTypeConversionImplicit(Type input_type, Type result_type); 211 static bool IsTypeConversionImplicit(int64_t value, Type result_type); 212 213 static const char* PrettyDescriptor(Type type); 214 215 private: 216 static constexpr size_t kObjectReferenceSize = 4u; 217 }; 218 std::ostream& operator<<(std::ostream& os, DataType::Type data_type); 219 220 // Defined outside DataType to have the operator<< available for DCHECK_NE(). 221 inline bool DataType::IsTypeConversionImplicit(Type input_type, Type result_type) { 222 DCHECK_NE(DataType::Type::kVoid, result_type); 223 DCHECK_NE(DataType::Type::kVoid, input_type); 224 225 // Invariant: We should never generate a conversion to a Boolean value. 226 DCHECK_NE(DataType::Type::kBool, result_type); 227 228 // Besides conversion to the same type, integral conversions to non-Int64 types 229 // are implicit if the result value range covers the input value range, i.e. 230 // widening conversions that do not need to trim the sign bits. 231 return result_type == input_type || 232 (result_type != Type::kInt64 && 233 IsIntegralType(input_type) && 234 IsIntegralType(result_type) && 235 MinValueOfIntegralType(input_type) >= MinValueOfIntegralType(result_type) && 236 MaxValueOfIntegralType(input_type) <= MaxValueOfIntegralType(result_type)); 237 } 238 239 inline bool DataType::IsTypeConversionImplicit(int64_t value, Type result_type) { 240 if (IsIntegralType(result_type) && result_type != Type::kInt64) { 241 // If the constant value falls in the range of the result_type, type 242 // conversion isn't needed. 243 return value >= MinValueOfIntegralType(result_type) && 244 value <= MaxValueOfIntegralType(result_type); 245 } 246 // Conversion isn't implicit if it's into non-integer types, or 64-bit int 247 // which may have different number of registers. 248 return false; 249 } 250 251 } // namespace art 252 253 #endif // ART_COMPILER_OPTIMIZING_DATA_TYPE_H_ 254