src/Types.h
author David Anderson <dvander@alliedmods.net>
Sat Dec 22 18:22:14 2012 -0800 (2012-12-22)
changeset 230 fb3cd08bc7fb
parent 222 0cde1379b29f
child 233 bbb498ccb4ac
permissions -rw-r--r--
Re-add LIFO stack optimizations.
     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     static Type *NewEnum(Zone *zone, Handle<String> name);
   108 
   109     static bool Compare(Type *left, Type *right);
   110 
   111     static Type *cast(Object *obj) {
   112         assert(!obj ||
   113                obj->is(MapKind_Type) ||
   114                obj->is(MapKind_FunctionType) ||
   115                obj->is(MapKind_StructType) ||
   116                obj->is(MapKind_ArrayType) ||
   117                obj->is(MapKind_ReferenceType));
   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     String *name() {
   189         assert(isEnum() || isStruct());
   190         return name_;
   191     }
   192 
   193     // GC Descriptor.
   194     static inline size_t offsetOfName() {
   195         return OFFSETOF(Type, name_);
   196     }
   197     // End GC Descriptor.
   198 
   199   protected:
   200     Kind kind_;
   201     PrimitiveType primitive_;
   202 
   203     // Primitives, arrays, and references.
   204     bool const_;
   205 
   206     // Enums and structs only.
   207     Barriered<String> name_;
   208 };
   209 
   210 class ReferenceType : public Type
   211 {
   212   public:
   213     static ReferenceType *New(Zone *zone, Handle<Type> contained);
   214     
   215     Type *contained() {
   216         return contained_;
   217     }
   218 
   219     // GC Descriptor.
   220     static inline size_t offsetOfContained() {
   221         return OFFSETOF(ReferenceType, contained_);
   222     }
   223     // End GC Descriptor.
   224 
   225     static ReferenceType *cast(Object *obj) {
   226         assert(!obj || obj->is(MapKind_ReferenceType));
   227         return (ReferenceType *)obj;
   228     }
   229 
   230   private:
   231     Barriered<Type> contained_;
   232 };
   233 
   234 class ArrayType : public Type
   235 {
   236   public:
   237     static const int DYNAMIC_ARRAY_SIZE = -1;
   238 
   239     static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
   240     static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
   241 
   242     Type *innermost() {
   243         assert(isArray());
   244         Type *temp = contained();
   245         while (temp->isArray())
   246             temp = ArrayType::cast(temp)->contained();
   247         return temp;
   248     }
   249 
   250     Type *contained() {
   251         return contained_;
   252     }
   253     bool isFixedLength() {
   254         assert(isArray());
   255         return elements_ > 0;
   256     }
   257     bool isCharArray() {
   258         return contained()->isPrimitive() &&
   259                contained()->primitive() == PrimitiveType_Char;
   260     }
   261     unsigned fixedLength() {
   262         assert(isFixedLength());
   263         return elements_;
   264     }
   265     unsigned levels() {
   266         assert(isArray());
   267         return levels_;
   268     }
   269     bool hasInlineElements() {
   270         assert(isArray());
   271 
   272         // We don't allocate traceable elements inline, since there's no
   273         // point to the optimization; we're going to be allocating lots of
   274         // objects anyway (in theory).
   275         return isFixedLength() && !contained()->isTraceable();
   276     }
   277 
   278     // Arrays of this type can be created with this cached map.
   279     ArrayMap *newMap() {
   280         return newMap_;
   281     }
   282     void setNewMap(ArrayMap *map) {
   283         assert(!newMap());
   284         newMap_ = map;
   285     }
   286 
   287     // GC Descriptor.
   288     static inline size_t offsetOfContained() {
   289         return OFFSETOF(ArrayType, contained_);
   290     }
   291     static inline size_t offsetOfNewMap() {
   292         return OFFSETOF(ArrayType, newMap_);
   293     }
   294     // End GC Descriptor.
   295 
   296     static ArrayType *cast(Object *obj) {
   297         assert(!obj || obj->is(MapKind_ArrayType));
   298         return (ArrayType *)obj;
   299     }
   300 
   301   private:
   302     int32 elements_;
   303     unsigned levels_;
   304     Barriered<Type> contained_;
   305     Barriered<ArrayMap> newMap_;
   306 };
   307 
   308 class StructType : public Type
   309 {
   310   public:
   311     static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
   312 
   313     FixedArray *fields() {
   314         assert(isStruct());
   315         return fields_;
   316     }
   317     Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
   318 
   319     // Objects of this type can be created with this cached map.
   320     StructMap *newMap() {
   321         return newMap_;
   322     }
   323     void setNewMap(StructMap *map) {
   324         assert(!newMap());
   325         newMap_ = map;
   326     }
   327 
   328     // GC Descriptor.
   329     static inline size_t offsetOfFields() {
   330         return OFFSETOF(StructType, fields_);
   331     }
   332     static inline size_t offsetOfNewMap() {
   333         return OFFSETOF(StructType, newMap_);
   334     }
   335     // End GC Descriptor.
   336 
   337     static StructType *cast(Object *obj) {
   338         assert(!obj || obj->is(MapKind_StructType));
   339         return (StructType *)obj;
   340     }
   341 
   342   private:
   343     // Structs only.
   344     Barriered<FixedArray> fields_;
   345     Barriered<StructMap> newMap_;
   346 };
   347 
   348 class FunctionType : public Type
   349 {
   350   public:
   351     static FunctionType *New(Zone *zone, TokenKind kind);
   352 
   353     Type *parameterAt(size_t i) {
   354         return Type::cast(parameters()->at(i));
   355     }
   356     Type *returnType() {
   357         assert(isFunction());
   358         return returnType_;
   359     }
   360     FixedArray *parameters() {
   361         assert(isFunction());
   362         return parameters_;
   363     }
   364     FixedArray *defaults() {
   365         assert(isFunction());
   366         return defaults_;
   367     }
   368     bool isNative() {
   369         return token_ == TOK_NATIVE;
   370     }
   371     bool isForward() {
   372         return token_ == TOK_FORWARD;
   373     }
   374     bool isNativeVariadic() {
   375         assert(isNative());
   376         return variadicNative_;
   377     }
   378     void setReturnType(Handle<Type> returnType) {
   379         assert(!returnType_);
   380         returnType_ = returnType;
   381     }
   382     void setParameterTypes(Handle<FixedArray> types) {
   383         assert(!parameters_);
   384         parameters_ = types;
   385     }
   386     TokenKind token() {
   387         return token_;
   388     }
   389 
   390     // GC Descriptor.
   391     static inline size_t offsetOfReturnType() {
   392         return OFFSETOF(FunctionType, returnType_);
   393     }
   394     static inline size_t offsetOfParameters() {
   395         return OFFSETOF(FunctionType, parameters_);
   396     }
   397     static inline size_t offsetOfDefaults() {
   398         return OFFSETOF(FunctionType, defaults_);
   399     }
   400     // End GC Descriptor.
   401 
   402     static FunctionType *cast(Object *obj) {
   403         assert(!obj || obj->is(MapKind_FunctionType));
   404         return (FunctionType *)obj;
   405     }
   406 
   407   private:
   408     // Functions only.
   409     Barriered<Type> returnType_;
   410     Barriered<FixedArray> parameters_;
   411     Barriered<FixedArray> defaults_;
   412     TokenKind token_;
   413     bool variadicNative_;
   414 };
   415 
   416 class BoxedPrimitive
   417 {
   418     PrimitiveType type_;
   419     union {
   420         int i_;
   421         float f_;
   422     };
   423 
   424   public:
   425     static BoxedPrimitive Int(int i) {
   426         BoxedPrimitive b;
   427         b.type_ = PrimitiveType_Int32;
   428         b.i_ = i;
   429         return b;
   430     }
   431     static BoxedPrimitive Float(float f) {
   432         BoxedPrimitive b;
   433         b.type_ = PrimitiveType_Float;
   434         b.f_ = f;
   435         return b;
   436     }
   437 
   438     PrimitiveType type() const {
   439         return type_;
   440     }
   441     int toInt() const {
   442         assert(type() == PrimitiveType_Int32);
   443         return i_;
   444     }
   445     float toFloat() const {
   446         assert(type() == PrimitiveType_Float);
   447         return f_;
   448     }
   449 };
   450 
   451 const char *GetTypeName(Type *type);
   452 
   453 }
   454 
   455 #endif // _include_jc_types_h_