src/Types.h
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 247 7721042bdb67
child 258 241d082d6d89
permissions -rw-r--r--
Initial implementation of module imports.
     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         // Importable types are mainly used during the compilation process
   117         // to distinguish between normal names and static imports.
   118         IMPORTABLE
   119     };
   120 
   121     void init(Kind kind, Type *root = NULL);
   122 
   123   private:
   124     Kind kind() {
   125         return root_->kind_;
   126     }
   127 
   128   public:   
   129     static Type *NewVoid(Zone *zone);
   130     static Type *NewUnchecked(Zone *zone);
   131     static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   132     static Type *NewString(Zone *zone);
   133     static Type *NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> type);
   134     static Type *NewImportable(Zone *zone);
   135 
   136     static Type *cast(Object *obj) {
   137         assert(!obj ||
   138                obj->is(MapKind_Type) ||
   139                obj->is(MapKind_FunctionType) ||
   140                obj->is(MapKind_StructType) ||
   141                obj->is(MapKind_ArrayType) ||
   142                obj->is(MapKind_ReferenceType) ||
   143                obj->is(MapKind_EnumType));
   144         return (Type *)obj;
   145     }
   146 
   147     bool isPrimitive() {
   148         return kind() == PRIMITIVE;
   149     }
   150     bool isArray() {
   151         return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
   152     }
   153     bool isReference() {
   154         return kind() == REFERENCE;
   155     }
   156     bool isFunction() {
   157         return kind() == FUNCTION;
   158     }
   159     bool isVoid() {
   160         return kind() == VOID;
   161     }
   162     bool isUnchecked() {
   163         return kind() == UNCHECKED;
   164     }
   165     bool isStruct() {
   166         return kind() == STRUCT;
   167     }
   168     bool isImportable() {
   169         return kind() == IMPORTABLE;
   170     }
   171     PrimitiveType primitive() {
   172         assert(isPrimitive());
   173         return root_->primitive_;
   174     }
   175     bool isPod() {
   176         return (isPrimitive() && !isString()) || isEnum() || isUnchecked();
   177     }
   178     PrimitiveType pod() {
   179         assert(isPod());
   180         return isPrimitive()
   181                ? (primitive() == PrimitiveType_Bool)
   182                  ? PrimitiveType_Int32
   183                  : primitive()
   184                : PrimitiveType_Int32;
   185     }
   186     bool isChar() {
   187         return isPrimitive() && primitive() == PrimitiveType_Char;
   188     }
   189     bool isFloat() {
   190         return isPrimitive() && primitive() == PrimitiveType_Float;
   191     }
   192     bool isInt32() {
   193         return isPrimitive() && primitive() == PrimitiveType_Int32;
   194     }
   195     bool isInt32OrEnum() {
   196         return isInt32() || isEnum();
   197     }
   198     bool isBool() {
   199         return isPrimitive() && primitive() == PrimitiveType_Bool;
   200     }
   201     bool isString() {
   202         return kind() == STRING;
   203     }
   204     bool isExternalArray() {
   205         return kind() == EXTERNAL_ARRAY;
   206     }
   207     bool isTraceable() {
   208         return kind() >= STRING;
   209     }
   210     bool isEnum() {
   211         return kind() == ENUM;
   212     }
   213     bool hasTypeQualifiers() {
   214         return kind_ == QUALTYPE;
   215     }
   216 
   217     TypeQualifiers quals() {
   218         if (!hasTypeQualifiers())
   219             return TypeQual_None;
   220         return quals_;
   221     }
   222     Type *unqualified() {
   223         return root_;
   224     }
   225 
   226     // GC Descriptor.
   227     static inline size_t offsetOfRoot() {
   228         return OFFSETOF(Type, root_);
   229     }
   230     // End GC Descriptor.
   231 
   232   protected:
   233     Kind kind_;
   234     PrimitiveType primitive_;
   235     TypeQualifiers quals_;
   236 
   237     // For unqualified types, this points to |this|. For qualified types, it
   238     // points to the unqualified original type.
   239     Barriered<Type> root_;
   240 };
   241 
   242 class EnumType : public Type
   243 {
   244   public:
   245     static EnumType *New(Zone *Zone, Handle<String> name);
   246 
   247     String *name() {
   248         return name_;
   249     }
   250 
   251     // GC Descriptor.
   252     static inline size_t offsetOfName() {
   253         return OFFSETOF(EnumType, name_);
   254     }
   255     // End GC Descriptor.
   256 
   257     static EnumType *cast(Object *obj) {
   258         assert(!obj || obj->is(MapKind_EnumType));
   259         return (EnumType *)obj;
   260     }
   261 
   262   private:
   263     Barriered<String> name_;
   264 };
   265 
   266 class ReferenceType : public Type
   267 {
   268   public:
   269     static ReferenceType *New(Zone *zone, Handle<Type> contained);
   270     
   271     Type *contained() {
   272         return contained_;
   273     }
   274 
   275     // GC Descriptor.
   276     static inline size_t offsetOfContained() {
   277         return OFFSETOF(ReferenceType, contained_);
   278     }
   279     // End GC Descriptor.
   280 
   281     static ReferenceType *cast(Type *obj) {
   282         if (!obj)
   283             return NULL;
   284         obj = obj->unqualified();
   285         assert(obj->is(MapKind_ReferenceType));
   286         return (ReferenceType *)obj;
   287     }
   288 
   289   private:
   290     Barriered<Type> contained_;
   291 };
   292 
   293 class ArrayType : public Type
   294 {
   295   public:
   296     static const int DYNAMIC_ARRAY_SIZE = -1;
   297 
   298     static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
   299     static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
   300 
   301     Type *innermost() {
   302         Type *temp = contained();
   303         while (temp->isArray())
   304             temp = ArrayType::cast(temp)->contained();
   305         return temp;
   306     }
   307 
   308     bool isDynamic() {
   309         return elements_ == DYNAMIC_ARRAY_SIZE;
   310     }
   311     bool isExtensible() {
   312         return isDynamic() && !(quals_ & TypeQual_Const);
   313     }
   314     Type *contained() {
   315         return contained_;
   316     }
   317     bool isFixedLength() {
   318         return elements_ > 0;
   319     }
   320     bool isCharArray() {
   321         return contained()->isPrimitive() &&
   322                contained()->primitive() == PrimitiveType_Char;
   323     }
   324     unsigned fixedLength() {
   325         assert(isFixedLength());
   326         return elements_;
   327     }
   328     unsigned levels() {
   329         return levels_;
   330     }
   331     bool hasInlineElements() {
   332         // We don't allocate traceable elements inline, since there's no
   333         // point to the optimization; we're going to be allocating lots of
   334         // objects anyway (in theory).
   335         return isFixedLength() && !contained()->isTraceable();
   336     }
   337 
   338     // Arrays of this type can be created with this cached map.
   339     ArrayMap *newMap() {
   340         return newMap_;
   341     }
   342     void setNewMap(ArrayMap *map) {
   343         assert(!newMap());
   344         newMap_ = map;
   345     }
   346 
   347     // GC Descriptor.
   348     static inline size_t offsetOfContained() {
   349         return OFFSETOF(ArrayType, contained_);
   350     }
   351     static inline size_t offsetOfNewMap() {
   352         return OFFSETOF(ArrayType, newMap_);
   353     }
   354     // End GC Descriptor.
   355 
   356     static ArrayType *cast(Type *obj) {
   357         if (!obj)
   358             return NULL;
   359         obj = obj->unqualified();
   360         assert(obj->is(MapKind_ArrayType));
   361         return (ArrayType *)obj;
   362     }
   363 
   364   private:
   365     int32 elements_;
   366     unsigned levels_;
   367     Barriered<Type> contained_;
   368     Barriered<ArrayMap> newMap_;
   369 };
   370 
   371 class StructType : public Type
   372 {
   373   public:
   374     static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
   375 
   376     FixedArray *fields() {
   377         assert(isStruct());
   378         return fields_;
   379     }
   380     Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
   381 
   382     // Objects of this type can be created with this cached map.
   383     StructMap *newMap() {
   384         return newMap_;
   385     }
   386     void setNewMap(StructMap *map) {
   387         assert(!newMap());
   388         newMap_ = map;
   389     }
   390 
   391     String *name() {
   392         return name_;
   393     }
   394 
   395     // GC Descriptor.
   396     static inline size_t offsetOfFields() {
   397         return OFFSETOF(StructType, fields_);
   398     }
   399     static inline size_t offsetOfNewMap() {
   400         return OFFSETOF(StructType, newMap_);
   401     }
   402     static inline size_t offsetOfName() {
   403         return OFFSETOF(StructType, name_);
   404     }
   405     // End GC Descriptor.
   406 
   407     static StructType *cast(Type *obj) {
   408         if (!obj)
   409             return NULL;
   410         obj = obj->unqualified();
   411         assert(obj->is(MapKind_StructType));
   412         return (StructType *)obj;
   413     }
   414 
   415   private:
   416     // Structs only.
   417     Barriered<FixedArray> fields_;
   418     Barriered<StructMap> newMap_;
   419     Barriered<String> name_;
   420 };
   421 
   422 class FunctionType : public Type
   423 {
   424   public:
   425     static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
   426 
   427     Type *parameterAt(size_t i) {
   428         return Type::cast(parameters()->at(i));
   429     }
   430     Type *returnType() {
   431         assert(isFunction());
   432         return returnType_;
   433     }
   434     FixedArray *parameters() {
   435         assert(isFunction());
   436         return parameters_;
   437     }
   438     FixedArray *defaults() {
   439         assert(isFunction());
   440         return defaults_;
   441     }
   442     bool isNative() {
   443         return token_ == TOK_NATIVE;
   444     }
   445     bool isForward() {
   446         return token_ == TOK_FORWARD;
   447     }
   448     bool isNativeVariadic() {
   449         assert(isNative());
   450         return variadicNative_;
   451     }
   452     void setVariadic() {
   453         assert(isNative());
   454         variadicNative_ = true;
   455     }
   456     void setReturnType(Handle<Type> returnType) {
   457         assert(!returnType_);
   458         returnType_ = returnType;
   459     }
   460     void setParameterTypes(Handle<FixedArray> types) {
   461         assert(!parameters_);
   462         parameters_ = types;
   463     }
   464     TokenKind token() {
   465         return token_;
   466     }
   467     String *name() {
   468         return name_;
   469     }
   470 
   471     // GC Descriptor.
   472     static inline size_t offsetOfReturnType() {
   473         return OFFSETOF(FunctionType, returnType_);
   474     }
   475     static inline size_t offsetOfParameters() {
   476         return OFFSETOF(FunctionType, parameters_);
   477     }
   478     static inline size_t offsetOfDefaults() {
   479         return OFFSETOF(FunctionType, defaults_);
   480     }
   481     static inline size_t offsetOfName() {
   482         return OFFSETOF(FunctionType, name_);
   483     }
   484     // End GC Descriptor.
   485 
   486     static FunctionType *cast(Type *obj) {
   487         if (!obj)
   488             return NULL;
   489         obj = obj->unqualified();
   490         assert(obj->is(MapKind_FunctionType));
   491         return (FunctionType *)obj;
   492     }
   493 
   494   private:
   495     // Functions only.
   496     Barriered<Type> returnType_;
   497     Barriered<FixedArray> parameters_;
   498     Barriered<FixedArray> defaults_;
   499     Barriered<String> name_;
   500     TokenKind token_;
   501     bool variadicNative_;
   502 };
   503 
   504 class BoxedPrimitive
   505 {
   506     PrimitiveType type_;
   507     union {
   508         int i_;
   509         float f_;
   510     };
   511 
   512   public:
   513     static BoxedPrimitive Int(int i) {
   514         BoxedPrimitive b;
   515         b.type_ = PrimitiveType_Int32;
   516         b.i_ = i;
   517         return b;
   518     }
   519     static BoxedPrimitive Float(float f) {
   520         BoxedPrimitive b;
   521         b.type_ = PrimitiveType_Float;
   522         b.f_ = f;
   523         return b;
   524     }
   525 
   526     PrimitiveType type() const {
   527         return type_;
   528     }
   529     int toInt() const {
   530         assert(type() == PrimitiveType_Int32);
   531         return i_;
   532     }
   533     float toFloat() const {
   534         assert(type() == PrimitiveType_Float);
   535         return f_;
   536     }
   537 };
   538 
   539 const char *GetTypeName(Type *type, char *buffer, size_t maxlen);
   540 
   541 }
   542 
   543 #endif // _include_jc_types_h_