src/Types.h
author David Anderson <dvander@alliedmods.net>
Sat Dec 22 23:18:57 2012 -0800 (2012-12-22)
changeset 233 bbb498ccb4ac
parent 222 0cde1379b29f
child 234 26e3035cdffc
permissions -rw-r--r--
Re-add enum support.
     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 Type *NewVoid(Zone *zone);
   105     static Type *NewUnchecked(Zone *zone);
   106     static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   107 
   108     static bool Compare(Type *left, Type *right);
   109 
   110     static Type *cast(Object *obj) {
   111         assert(!obj ||
   112                obj->is(MapKind_Type) ||
   113                obj->is(MapKind_FunctionType) ||
   114                obj->is(MapKind_StructType) ||
   115                obj->is(MapKind_ArrayType) ||
   116                obj->is(MapKind_ReferenceType) ||
   117                obj->is(MapKind_EnumType));
   118         return (Type *)obj;
   119     }
   120 
   121     bool isPrimitive() {
   122         return kind() == PRIMITIVE;
   123     }
   124     bool isArray() {
   125         return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
   126     }
   127     bool isReference() {
   128         return kind() == REFERENCE;
   129     }
   130     bool isFunction() {
   131         return kind() == FUNCTION;
   132     }
   133     bool isVoid() {
   134         return kind() == VOID;
   135     }
   136     bool isUnchecked() {
   137         return kind() == UNCHECKED;
   138     }
   139     bool isStruct() {
   140         return kind() == STRUCT;
   141     }
   142     PrimitiveType primitive() {
   143         assert(isPrimitive());
   144         return primitive_;
   145     }
   146     bool isPod() {
   147         return isPrimitive() || isEnum() || isUnchecked();
   148     }
   149     PrimitiveType pod() {
   150         assert(isPod());
   151         return isPrimitive()
   152                ? (primitive() == PrimitiveType_Bool)
   153                  ? PrimitiveType_Int32
   154                  : primitive()
   155                : PrimitiveType_Int32;
   156     }
   157     bool isChar() {
   158         return isPrimitive() && primitive() == PrimitiveType_Char;
   159     }
   160     bool isFloat() {
   161         return isPrimitive() && primitive() == PrimitiveType_Float;
   162     }
   163     bool isInt32() {
   164         return isPrimitive() && primitive() == PrimitiveType_Int32;
   165     }
   166     bool isInt32OrEnum() {
   167         return isInt32() || isEnum();
   168     }
   169     bool isBool() {
   170         return isPrimitive() && primitive() == PrimitiveType_Bool;
   171     }
   172     bool isExternalArray() {
   173         return kind() == EXTERNAL_ARRAY;
   174     }
   175     bool isTraceable() {
   176         return !isPrimitive();
   177     }
   178     bool isConst() {
   179         assert(isPrimitive() ||
   180                isArray() ||
   181                isReference());
   182         return const_;
   183     }
   184     bool isEnum() {
   185         return kind() == ENUM;
   186     }
   187 
   188   protected:
   189     Kind kind_;
   190     PrimitiveType primitive_;
   191 
   192     // Primitives, arrays, and references.
   193     bool const_;
   194 };
   195 
   196 class EnumType : public Type
   197 {
   198   public:
   199     static EnumType *New(Zone *Zone, Handle<String> name);
   200 
   201     String *name() {
   202         return name_;
   203     }
   204 
   205     // GC Descriptor.
   206     static inline size_t offsetOfName() {
   207         return OFFSETOF(EnumType, name_);
   208     }
   209     // End GC Descriptor.
   210 
   211     static EnumType *cast(Object *obj) {
   212         assert(!obj || obj->is(MapKind_EnumType));
   213         return (EnumType *)obj;
   214     }
   215 
   216   private:
   217     Barriered<String> name_;
   218 };
   219 
   220 class ReferenceType : public Type
   221 {
   222   public:
   223     static ReferenceType *New(Zone *zone, Handle<Type> contained);
   224     
   225     Type *contained() {
   226         return contained_;
   227     }
   228 
   229     // GC Descriptor.
   230     static inline size_t offsetOfContained() {
   231         return OFFSETOF(ReferenceType, contained_);
   232     }
   233     // End GC Descriptor.
   234 
   235     static ReferenceType *cast(Object *obj) {
   236         assert(!obj || obj->is(MapKind_ReferenceType));
   237         return (ReferenceType *)obj;
   238     }
   239 
   240   private:
   241     Barriered<Type> contained_;
   242 };
   243 
   244 class ArrayType : public Type
   245 {
   246   public:
   247     static const int DYNAMIC_ARRAY_SIZE = -1;
   248 
   249     static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
   250     static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
   251 
   252     Type *innermost() {
   253         assert(isArray());
   254         Type *temp = contained();
   255         while (temp->isArray())
   256             temp = ArrayType::cast(temp)->contained();
   257         return temp;
   258     }
   259 
   260     Type *contained() {
   261         return contained_;
   262     }
   263     bool isFixedLength() {
   264         assert(isArray());
   265         return elements_ > 0;
   266     }
   267     bool isCharArray() {
   268         return contained()->isPrimitive() &&
   269                contained()->primitive() == PrimitiveType_Char;
   270     }
   271     unsigned fixedLength() {
   272         assert(isFixedLength());
   273         return elements_;
   274     }
   275     unsigned levels() {
   276         assert(isArray());
   277         return levels_;
   278     }
   279     bool hasInlineElements() {
   280         assert(isArray());
   281 
   282         // We don't allocate traceable elements inline, since there's no
   283         // point to the optimization; we're going to be allocating lots of
   284         // objects anyway (in theory).
   285         return isFixedLength() && !contained()->isTraceable();
   286     }
   287 
   288     // Arrays of this type can be created with this cached map.
   289     ArrayMap *newMap() {
   290         return newMap_;
   291     }
   292     void setNewMap(ArrayMap *map) {
   293         assert(!newMap());
   294         newMap_ = map;
   295     }
   296 
   297     // GC Descriptor.
   298     static inline size_t offsetOfContained() {
   299         return OFFSETOF(ArrayType, contained_);
   300     }
   301     static inline size_t offsetOfNewMap() {
   302         return OFFSETOF(ArrayType, newMap_);
   303     }
   304     // End GC Descriptor.
   305 
   306     static ArrayType *cast(Object *obj) {
   307         assert(!obj || obj->is(MapKind_ArrayType));
   308         return (ArrayType *)obj;
   309     }
   310 
   311   private:
   312     int32 elements_;
   313     unsigned levels_;
   314     Barriered<Type> contained_;
   315     Barriered<ArrayMap> newMap_;
   316 };
   317 
   318 class StructType : public Type
   319 {
   320   public:
   321     static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
   322 
   323     FixedArray *fields() {
   324         assert(isStruct());
   325         return fields_;
   326     }
   327     Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
   328 
   329     // Objects of this type can be created with this cached map.
   330     StructMap *newMap() {
   331         return newMap_;
   332     }
   333     void setNewMap(StructMap *map) {
   334         assert(!newMap());
   335         newMap_ = map;
   336     }
   337 
   338     String *name() {
   339         return name_;
   340     }
   341 
   342     // GC Descriptor.
   343     static inline size_t offsetOfFields() {
   344         return OFFSETOF(StructType, fields_);
   345     }
   346     static inline size_t offsetOfNewMap() {
   347         return OFFSETOF(StructType, newMap_);
   348     }
   349     static inline size_t offsetOfName() {
   350         return OFFSETOF(StructType, name_);
   351     }
   352     // End GC Descriptor.
   353 
   354     static StructType *cast(Object *obj) {
   355         assert(!obj || obj->is(MapKind_StructType));
   356         return (StructType *)obj;
   357     }
   358 
   359   private:
   360     // Structs only.
   361     Barriered<FixedArray> fields_;
   362     Barriered<StructMap> newMap_;
   363     Barriered<String> name_;
   364 };
   365 
   366 class FunctionType : public Type
   367 {
   368   public:
   369     static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
   370 
   371     Type *parameterAt(size_t i) {
   372         return Type::cast(parameters()->at(i));
   373     }
   374     Type *returnType() {
   375         assert(isFunction());
   376         return returnType_;
   377     }
   378     FixedArray *parameters() {
   379         assert(isFunction());
   380         return parameters_;
   381     }
   382     FixedArray *defaults() {
   383         assert(isFunction());
   384         return defaults_;
   385     }
   386     bool isNative() {
   387         return token_ == TOK_NATIVE;
   388     }
   389     bool isForward() {
   390         return token_ == TOK_FORWARD;
   391     }
   392     bool isNativeVariadic() {
   393         assert(isNative());
   394         return variadicNative_;
   395     }
   396     void setReturnType(Handle<Type> returnType) {
   397         assert(!returnType_);
   398         returnType_ = returnType;
   399     }
   400     void setParameterTypes(Handle<FixedArray> types) {
   401         assert(!parameters_);
   402         parameters_ = types;
   403     }
   404     TokenKind token() {
   405         return token_;
   406     }
   407     String *name() {
   408         return name_;
   409     }
   410 
   411     // GC Descriptor.
   412     static inline size_t offsetOfReturnType() {
   413         return OFFSETOF(FunctionType, returnType_);
   414     }
   415     static inline size_t offsetOfParameters() {
   416         return OFFSETOF(FunctionType, parameters_);
   417     }
   418     static inline size_t offsetOfDefaults() {
   419         return OFFSETOF(FunctionType, defaults_);
   420     }
   421     static inline size_t offsetOfName() {
   422         return OFFSETOF(FunctionType, name_);
   423     }
   424     // End GC Descriptor.
   425 
   426     static FunctionType *cast(Object *obj) {
   427         assert(!obj || obj->is(MapKind_FunctionType));
   428         return (FunctionType *)obj;
   429     }
   430 
   431   private:
   432     // Functions only.
   433     Barriered<Type> returnType_;
   434     Barriered<FixedArray> parameters_;
   435     Barriered<FixedArray> defaults_;
   436     Barriered<String> name_;
   437     TokenKind token_;
   438     bool variadicNative_;
   439 };
   440 
   441 class BoxedPrimitive
   442 {
   443     PrimitiveType type_;
   444     union {
   445         int i_;
   446         float f_;
   447     };
   448 
   449   public:
   450     static BoxedPrimitive Int(int i) {
   451         BoxedPrimitive b;
   452         b.type_ = PrimitiveType_Int32;
   453         b.i_ = i;
   454         return b;
   455     }
   456     static BoxedPrimitive Float(float f) {
   457         BoxedPrimitive b;
   458         b.type_ = PrimitiveType_Float;
   459         b.f_ = f;
   460         return b;
   461     }
   462 
   463     PrimitiveType type() const {
   464         return type_;
   465     }
   466     int toInt() const {
   467         assert(type() == PrimitiveType_Int32);
   468         return i_;
   469     }
   470     float toFloat() const {
   471         assert(type() == PrimitiveType_Float);
   472         return f_;
   473     }
   474 };
   475 
   476 const char *GetTypeName(Type *type);
   477 
   478 }
   479 
   480 #endif // _include_jc_types_h_