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