src/Types.h
author David Anderson <dvander@alliedmods.net>
Sun Sep 02 13:06:09 2012 -0700 (2012-09-02)
changeset 177 56f7e5b0243c
parent 172 48cffae8c9e0
child 184 387d76b1e981
permissions -rw-r--r--
Fix bug in bytecode resizing.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jc_types_h_
    20 #define _include_jc_types_h_
    21 
    22 #include "Heap.h"
    23 #include "Barriers.h"
    24 #include "FixedArray.h"
    25 
    26 namespace ke {
    27 
    28 class String;
    29 class Descriptor;
    30 
    31 enum PrimitiveType
    32 {
    33     // A boolean type semantically represents 0 or 1. As an optimization, its
    34     // internal storage type is the same as int32, and any non-zero value
    35     // compares positively to "true".
    36     PrimitiveType_Bool,
    37 
    38     // A character is an arbitrary 8-bit value. Characters are not supported
    39     // as a normal storage class; they may only be used for arrays. When read
    40     // from an array, they are immediately sign extended to 32 bits. Integers
    41     // stored into an char array are truncated to 8 bits.
    42     PrimitiveType_Char,         // signed, 8-bit character
    43 
    44     // Enumerations and untyped variables are stored as signed, 32-bit integers.
    45     PrimitiveType_Int32,
    46 
    47     // Floating point values are 32-bit IEEE-754 floats. This is required ro
    48     // SourcePawn 1 compatibility.
    49     PrimitiveType_Float,
    50 
    51     // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
    52     // on 64-bit systems), and does not exist in language semantics.
    53     PrimitiveType_Native,
    54 
    55     PrimitiveTypes_Total
    56 };
    57 
    58 class Type : public Object
    59 {
    60     enum Kind {
    61         // A primitive is a plain-old-data type.
    62         PRIMITIVE,
    63 
    64         // An array is a fixed-length vector of any other type.
    65         ARRAY,
    66 
    67         // A reference type may only be specified on parameters, and
    68         // references may only be computed to primitives or enums.
    69         REFERENCE,
    70 
    71         // A function type encapsulates a function signature.
    72         FUNCTION,
    73 
    74         // A native is a limited type of function used for system calls.
    75         NATIVE,
    76 
    77         // Void is an internal type used to specify that a function returns no
    78         // value.
    79         VOID,
    80 
    81         // Enums are plain-old-data with int32 storage. They allow for extra
    82         // type checking that would not be possible with integers.
    83         ENUM,
    84 
    85         // Structs are composite records that may contain primitives, arrays,
    86         // functions, enums, and other structs.
    87         STRUCT,
    88 
    89         // Unchecked is a magic type that has implicit, bitwise coercion to
    90         // int32, float, bool, or an enum.
    91         UNCHECKED
    92     };
    93 
    94   private:
    95     Kind kind() {
    96         return kind_;
    97     }
    98 
    99   public:
   100     static const int UNKNOWN_SIZE = -1;
   101     static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
   102     
   103     static Type *NewVoid(Zone *zone);
   104     static Type *NewUnchecked(Zone *zone);
   105     static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   106     static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
   107     static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
   108     static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   109                              Handle<FixedArray> defaults);
   110     static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   111                            Handle<FixedArray> defaults, bool isVariadic);
   112     static Type *NewEnum(Zone *zone, Handle<String> name);
   113     static Type *NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap);
   114 
   115     static bool Compare(Type *left, Type *right);
   116 
   117     static Type *cast(Object *obj) {
   118         assert(!obj || obj->is(MapKind_Type));
   119         return (Type *)obj;
   120     }
   121 
   122     bool isPrimitive() {
   123         return kind() == PRIMITIVE;
   124     }
   125     bool isArray() {
   126         return kind() == ARRAY;
   127     }
   128     bool isReference() {
   129         return kind() == REFERENCE;
   130     }
   131     bool isFunction() {
   132         return kind() == FUNCTION || kind() == NATIVE;
   133     }
   134     bool isNative() {
   135         return kind() == NATIVE;
   136     }
   137     bool isVoid() {
   138         return kind() == VOID;
   139     }
   140     bool isUnchecked() {
   141         return kind() == UNCHECKED;
   142     }
   143     bool isStruct() {
   144         return kind() == STRUCT;
   145     }
   146     bool isNativeVariadic() {
   147         assert(isNative());
   148         return variadicNative_;
   149     }
   150     PrimitiveType primitive() {
   151         assert(isPrimitive());
   152         return primitive_;
   153     }
   154     bool isPod() {
   155         return isPrimitive() || isEnum() || isUnchecked();
   156     }
   157     PrimitiveType pod() {
   158         assert(isPod());
   159         return isPrimitive()
   160                ? (primitive() == PrimitiveType_Bool)
   161                  ? PrimitiveType_Int32
   162                  : primitive()
   163                : PrimitiveType_Int32;
   164     }
   165     Type *contained() {
   166         assert(isArray() || isReference());
   167         return Type::cast(contained_);
   168     }
   169     int elements() {
   170         assert(isArray());
   171         return elements_;
   172     }
   173     unsigned levels() {
   174         assert(isArray());
   175         return levels_;
   176     }
   177     Type *innermost() {
   178         assert(isArray());
   179         Type *temp = contained();
   180         while (temp->isArray())
   181             temp = temp->contained();
   182         return temp;
   183     }
   184     bool isFloat() {
   185         return isPrimitive() && primitive() == PrimitiveType_Float;
   186     }
   187     bool isInt32() {
   188         return isPrimitive() && primitive() == PrimitiveType_Int32;
   189     }
   190     bool isInt32OrEnum() {
   191         return isInt32() || isEnum();
   192     }
   193     bool isBool() {
   194         return isPrimitive() && primitive() == PrimitiveType_Bool;
   195     }
   196     bool isCharArray() {
   197         return isArray() &&
   198                contained()->isPrimitive() &&
   199                contained()->primitive() == PrimitiveType_Char;
   200     }
   201     Type *returnType() {
   202         assert(isFunction());
   203         return returnType_;
   204     }
   205     FixedArray *parameters() {
   206         assert(isFunction());
   207         return parameters_;
   208     }
   209     FixedArray *defaults() {
   210         assert(isFunction());
   211         return defaults_;
   212     }
   213     Type *parameterAt(size_t i) {
   214         return Type::cast(parameters()->at(i));
   215     }
   216     bool isTraceable() {
   217         return !isPrimitive();
   218     }
   219     bool isConst() {
   220         assert(kind() == PRIMITIVE || kind() == ARRAY || kind() == REFERENCE);
   221         return const_;
   222     }
   223     bool isEnum() {
   224         return kind() == ENUM;
   225     }
   226 
   227     String *name() {
   228         assert(isEnum() || isStruct());
   229         return name_;
   230     }
   231     FixedArray *fields() {
   232         assert(isStruct());
   233         return fields_;
   234     }
   235     Descriptor *lookupField(Handle<String> name, unsigned *index);
   236 
   237     // Objects of this type can be created with this cached map.
   238     Map *newMap() {
   239         assert(isStruct() || isArray());
   240         return newMap_;
   241     }
   242     void setNewMap(Map *map) {
   243         assert(!newMap());
   244         newMap_ = map;
   245     }
   246 
   247     // GC Descriptor.
   248     static inline size_t offsetOfContained() {
   249         return OFFSETOF(Type, contained_);
   250     }
   251     static inline size_t offsetOfReturnType() {
   252         return OFFSETOF(Type, returnType_);
   253     }
   254     static inline size_t offsetOfParameters() {
   255         return OFFSETOF(Type, parameters_);
   256     }
   257     static inline size_t offsetOfName() {
   258         return OFFSETOF(Type, name_);
   259     }
   260     static inline size_t offsetOfFields() {
   261         return OFFSETOF(Type, fields_);
   262     }
   263     static inline size_t offsetOfNewMap() {
   264         return OFFSETOF(Type, newMap_);
   265     }
   266     static inline size_t offsetOfDefaults() {
   267         return OFFSETOF(Type, defaults_);
   268     }
   269     // End GC Descriptor.
   270 
   271   private:
   272     Kind kind_;
   273     PrimitiveType primitive_;
   274 
   275     // Primitives, arrays, and references.
   276     bool const_;
   277 
   278     // Arrays only.
   279     int32 elements_;
   280     unsigned levels_;
   281 
   282     // Arrays and references only.
   283     Barriered<Type> contained_;
   284 
   285     // Functions only.
   286     Barriered<Type> returnType_;
   287     Barriered<FixedArray> parameters_;
   288     Barriered<FixedArray> defaults_;
   289     bool variadicNative_;
   290 
   291     // Enums and structs only.
   292     Barriered<String> name_;
   293 
   294     // Structs only.
   295     Barriered<FixedArray> fields_;
   296     Barriered<Map> newMap_;
   297 };
   298 
   299 class BoxedPrimitive
   300 {
   301     PrimitiveType type_;
   302     union {
   303         int i_;
   304         float f_;
   305     };
   306 
   307   public:
   308     static BoxedPrimitive Int(int i) {
   309         BoxedPrimitive b;
   310         b.type_ = PrimitiveType_Int32;
   311         b.i_ = i;
   312         return b;
   313     }
   314     static BoxedPrimitive Float(float f) {
   315         BoxedPrimitive b;
   316         b.type_ = PrimitiveType_Float;
   317         b.f_ = f;
   318         return b;
   319     }
   320 
   321     PrimitiveType type() const {
   322         return type_;
   323     }
   324     int toInt() const {
   325         assert(type() == PrimitiveType_Int32);
   326         return i_;
   327     }
   328     float toFloat() const {
   329         assert(type() == PrimitiveType_Float);
   330         return f_;
   331     }
   332 };
   333 
   334 }
   335 
   336 #endif // _include_jc_types_h_