Home | History | Annotate | Download | only in dex
      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 
     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 
     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 
     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 
     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 
    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.
    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.
    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|.
    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.
    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 
    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