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