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