src/Types.h
author David Anderson <dvander@alliedmods.net>
Sun Sep 16 21:59:26 2012 -0700 (2012-09-16)
changeset 190 dd04fce774cd
parent 188 bab29bcec7fe
child 195 c1ba166f3fc4
permissions -rw-r--r--
Enable dynamic array declarations.
     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 #define MAX_ARRAY_DEPTH     5
    32 
    33 enum PrimitiveType
    34 {
    35     // A boolean type semantically represents 0 or 1. As an optimization, its
    36     // internal storage type is the same as int32, and any non-zero value
    37     // compares positively to "true".
    38     PrimitiveType_Bool,
    39 
    40     // A character is an arbitrary 8-bit value. Characters are not supported
    41     // as a normal storage class; they may only be used for arrays. When read
    42     // from an array, they are immediately sign extended to 32 bits. Integers
    43     // stored into an char array are truncated to 8 bits.
    44     PrimitiveType_Char,         // signed, 8-bit character
    45 
    46     // Enumerations and untyped variables are stored as signed, 32-bit integers.
    47     PrimitiveType_Int32,
    48 
    49     // Floating point values are 32-bit IEEE-754 floats. This is required ro
    50     // SourcePawn 1 compatibility.
    51     PrimitiveType_Float,
    52 
    53     // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
    54     // on 64-bit systems), and does not exist in language semantics.
    55     PrimitiveType_Native,
    56 
    57     PrimitiveTypes_Total
    58 };
    59 
    60 class Type : public Object
    61 {
    62     enum Kind {
    63         // A primitive is a plain-old-data type.
    64         PRIMITIVE,
    65 
    66         // An array is a fixed-length vector of any other type.
    67         ARRAY,
    68         EXTERNAL_ARRAY,
    69 
    70         // A reference type may only be specified on parameters, and
    71         // references may only be computed to primitives or enums.
    72         REFERENCE,
    73 
    74         // A function type encapsulates a function signature.
    75         FUNCTION,
    76 
    77         // A native is a limited type of function used for system calls.
    78         NATIVE,
    79 
    80         // Void is an internal type used to specify that a function returns no
    81         // value.
    82         VOID,
    83 
    84         // Enums are plain-old-data with int32 storage. They allow for extra
    85         // type checking that would not be possible with integers.
    86         ENUM,
    87 
    88         // Structs are composite records that may contain primitives, arrays,
    89         // functions, enums, and other structs.
    90         STRUCT,
    91 
    92         // Unchecked is a magic type that has implicit, bitwise coercion to
    93         // int32, float, bool, or an enum.
    94         UNCHECKED
    95     };
    96 
    97   private:
    98     Kind kind() {
    99         return kind_;
   100     }
   101 
   102   public:
   103     static const int DYNAMIC_ARRAY_SIZE = -1;
   104     
   105     static Type *NewVoid(Zone *zone);
   106     static Type *NewUnchecked(Zone *zone);
   107     static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   108     static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
   109     static Type *NewExternalArray(Zone *zone, Handle<Type> contained);
   110     static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
   111     static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   112                              Handle<FixedArray> defaults);
   113     static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   114                            Handle<FixedArray> defaults, bool isVariadic);
   115     static Type *NewEnum(Zone *zone, Handle<String> name);
   116     static Type *NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap);
   117 
   118     static bool Compare(Type *left, Type *right);
   119 
   120     static Type *cast(Object *obj) {
   121         assert(!obj || obj->is(MapKind_Type));
   122         return (Type *)obj;
   123     }
   124 
   125     bool isPrimitive() {
   126         return kind() == PRIMITIVE;
   127     }
   128     bool isArray() {
   129         return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
   130     }
   131     bool isReference() {
   132         return kind() == REFERENCE;
   133     }
   134     bool isFunction() {
   135         return kind() == FUNCTION || kind() == NATIVE;
   136     }
   137     bool isNative() {
   138         return kind() == NATIVE;
   139     }
   140     bool isVoid() {
   141         return kind() == VOID;
   142     }
   143     bool isUnchecked() {
   144         return kind() == UNCHECKED;
   145     }
   146     bool isStruct() {
   147         return kind() == STRUCT;
   148     }
   149     bool isNativeVariadic() {
   150         assert(isNative());
   151         return variadicNative_;
   152     }
   153     PrimitiveType primitive() {
   154         assert(isPrimitive());
   155         return primitive_;
   156     }
   157     bool isPod() {
   158         return isPrimitive() || isEnum() || isUnchecked();
   159     }
   160     PrimitiveType pod() {
   161         assert(isPod());
   162         return isPrimitive()
   163                ? (primitive() == PrimitiveType_Bool)
   164                  ? PrimitiveType_Int32
   165                  : primitive()
   166                : PrimitiveType_Int32;
   167     }
   168     Type *contained() {
   169         assert(isArray() || isReference());
   170         return Type::cast(contained_);
   171     }
   172     bool isFixedLength() {
   173         assert(isArray());
   174         return elements_ > 0;
   175     }
   176     unsigned fixedLength() {
   177         assert(isFixedLength());
   178         return elements_;
   179     }
   180     unsigned levels() {
   181         assert(isArray());
   182         return levels_;
   183     }
   184     bool hasInlineElements() {
   185         assert(isArray());
   186 
   187         // We don't allocate traceable elements inline, since there's no
   188         // point to the optimization; we're going to be allocating lots of
   189         // objects anyway (in theory).
   190         return isFixedLength() && !contained()->isTraceable();
   191     }
   192     Type *innermost() {
   193         assert(isArray());
   194         Type *temp = contained();
   195         while (temp->isArray())
   196             temp = temp->contained();
   197         return temp;
   198     }
   199     bool isFloat() {
   200         return isPrimitive() && primitive() == PrimitiveType_Float;
   201     }
   202     bool isInt32() {
   203         return isPrimitive() && primitive() == PrimitiveType_Int32;
   204     }
   205     bool isInt32OrEnum() {
   206         return isInt32() || isEnum();
   207     }
   208     bool isBool() {
   209         return isPrimitive() && primitive() == PrimitiveType_Bool;
   210     }
   211     bool isCharArray() {
   212         return isArray() &&
   213                contained()->isPrimitive() &&
   214                contained()->primitive() == PrimitiveType_Char;
   215     }
   216     bool isExternalArray() {
   217         return kind() == EXTERNAL_ARRAY;
   218     }
   219     Type *returnType() {
   220         assert(isFunction());
   221         return returnType_;
   222     }
   223     FixedArray *parameters() {
   224         assert(isFunction());
   225         return parameters_;
   226     }
   227     FixedArray *defaults() {
   228         assert(isFunction());
   229         return defaults_;
   230     }
   231     Type *parameterAt(size_t i) {
   232         return Type::cast(parameters()->at(i));
   233     }
   234     bool isTraceable() {
   235         return !isPrimitive();
   236     }
   237     bool isConst() {
   238         assert(isPrimitive() ||
   239                isArray() ||
   240                isReference());
   241         return const_;
   242     }
   243     bool isEnum() {
   244         return kind() == ENUM;
   245     }
   246 
   247     String *name() {
   248         assert(isEnum() || isStruct());
   249         return name_;
   250     }
   251     FixedArray *fields() {
   252         assert(isStruct());
   253         return fields_;
   254     }
   255     Descriptor *lookupField(Handle<String> name, unsigned *index);
   256 
   257     // Objects of this type can be created with this cached map.
   258     Map *newMap() {
   259         assert(isStruct() || isArray());
   260         return newMap_;
   261     }
   262     void setNewMap(Map *map) {
   263         assert(!newMap());
   264         newMap_ = map;
   265     }
   266 
   267     // GC Descriptor.
   268     static inline size_t offsetOfContained() {
   269         return OFFSETOF(Type, contained_);
   270     }
   271     static inline size_t offsetOfReturnType() {
   272         return OFFSETOF(Type, returnType_);
   273     }
   274     static inline size_t offsetOfParameters() {
   275         return OFFSETOF(Type, parameters_);
   276     }
   277     static inline size_t offsetOfName() {
   278         return OFFSETOF(Type, name_);
   279     }
   280     static inline size_t offsetOfFields() {
   281         return OFFSETOF(Type, fields_);
   282     }
   283     static inline size_t offsetOfNewMap() {
   284         return OFFSETOF(Type, newMap_);
   285     }
   286     static inline size_t offsetOfDefaults() {
   287         return OFFSETOF(Type, defaults_);
   288     }
   289     // End GC Descriptor.
   290 
   291   private:
   292     Kind kind_;
   293     PrimitiveType primitive_;
   294 
   295     // Primitives, arrays, and references.
   296     bool const_;
   297 
   298     // Arrays only.
   299     int32 elements_;
   300     unsigned levels_;
   301 
   302     // Arrays and references only.
   303     Barriered<Type> contained_;
   304 
   305     // Functions only.
   306     Barriered<Type> returnType_;
   307     Barriered<FixedArray> parameters_;
   308     Barriered<FixedArray> defaults_;
   309     bool variadicNative_;
   310 
   311     // Enums and structs only.
   312     Barriered<String> name_;
   313 
   314     // Structs only.
   315     Barriered<FixedArray> fields_;
   316     Barriered<Map> newMap_;
   317 };
   318 
   319 class BoxedPrimitive
   320 {
   321     PrimitiveType type_;
   322     union {
   323         int i_;
   324         float f_;
   325     };
   326 
   327   public:
   328     static BoxedPrimitive Int(int i) {
   329         BoxedPrimitive b;
   330         b.type_ = PrimitiveType_Int32;
   331         b.i_ = i;
   332         return b;
   333     }
   334     static BoxedPrimitive Float(float f) {
   335         BoxedPrimitive b;
   336         b.type_ = PrimitiveType_Float;
   337         b.f_ = f;
   338         return b;
   339     }
   340 
   341     PrimitiveType type() const {
   342         return type_;
   343     }
   344     int toInt() const {
   345         assert(type() == PrimitiveType_Int32);
   346         return i_;
   347     }
   348     float toFloat() const {
   349         assert(type() == PrimitiveType_Float);
   350         return f_;
   351     }
   352 };
   353 
   354 }
   355 
   356 #endif // _include_jc_types_h_