dvander@44: /* vim: set ts=4 sw=4 tw=99 et: dvander@44: * dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@0: #ifndef _include_jc_types_h_ dvander@0: #define _include_jc_types_h_ dvander@0: dvander@11: #include "Heap.h" dvander@13: #include "Barriers.h" dvander@14: #include "FixedArray.h" dvander@0: dvander@59: namespace ke { dvander@0: dvander@54: class String; dvander@148: class Descriptor; dvander@54: dvander@0: enum PrimitiveType dvander@0: { dvander@145: // A boolean type semantically represents 0 or 1. As an optimization, its dvander@145: // internal storage type is the same as int32, and any non-zero value dvander@145: // compares positively to "true". dvander@145: PrimitiveType_Bool, dvander@145: dvander@145: // A character is an arbitrary 8-bit value. Characters are not supported dvander@145: // as a normal storage class; they may only be used for arrays. When read dvander@145: // from an array, they are immediately sign extended to 32 bits. Integers dvander@145: // stored into an char array are truncated to 8 bits. dvander@21: PrimitiveType_Char, // signed, 8-bit character dvander@145: dvander@145: // Enumerations and untyped variables are stored as signed, 32-bit integers. dvander@145: PrimitiveType_Int32, dvander@145: dvander@145: // Floating point values are 32-bit IEEE-754 floats. This is required ro dvander@145: // SourcePawn 1 compatibility. dvander@145: PrimitiveType_Float, dvander@145: dvander@145: // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit dvander@145: // on 64-bit systems), and does not exist in language semantics. dvander@145: PrimitiveType_Native, dvander@145: dvander@11: PrimitiveTypes_Total dvander@0: }; dvander@0: dvander@12: class Type : public Object dvander@0: { dvander@0: enum Kind { dvander@0: PRIMITIVE, dvander@14: ARRAY, dvander@14: REFERENCE, dvander@68: FUNCTION, dvander@71: NATIVE, dvander@145: VOID, dvander@146: ENUM, dvander@146: STRUCT dvander@0: }; dvander@0: dvander@11: private: dvander@11: Kind kind() { dvander@13: return kind_; dvander@11: } dvander@11: dvander@0: public: dvander@0: static const int UNKNOWN_SIZE = -1; dvander@0: static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5; dvander@11: dvander@71: static Type *NewVoid(Zone *zone); dvander@12: static Type *NewPrimitive(Zone *zone, PrimitiveType type); dvander@41: static Type *NewArray(Zone *zone, Handle contained, int elements, bool isConst); dvander@67: static Type *NewReference(Zone *zone, Handle contained, bool isConst); dvander@41: static Type *NewFunction(Zone *zone, Handle returnType, Handle parameters); dvander@68: static Type *NewNative(Zone *zone, Handle returnType, Handle parameters, bool isVariadic); dvander@145: static Type *NewEnum(Zone *zone, Handle name); dvander@147: static Type *NewStruct(Zone *zone, Handle name, Handle fields, Handle newMap); dvander@0: dvander@63: static bool Compare(Type *left, Type *right); dvander@63: dvander@11: static Type *cast(Object *obj) { dvander@41: assert(!obj || obj->is(MapKind_Type)); dvander@11: return (Type *)obj; dvander@0: } dvander@11: dvander@11: bool isPrimitive() { dvander@11: return kind() == PRIMITIVE; dvander@11: } dvander@11: bool isArray() { dvander@14: return kind() == ARRAY; dvander@0: } dvander@14: bool isReference() { dvander@14: return kind() == REFERENCE; dvander@14: } dvander@14: bool isFunction() { dvander@68: return kind() == FUNCTION || kind() == NATIVE; dvander@68: } dvander@68: bool isNative() { dvander@68: return kind() == NATIVE; dvander@68: } dvander@71: bool isVoid() { dvander@71: return kind() == VOID; dvander@71: } dvander@147: bool isStruct() { dvander@147: return kind() == STRUCT; dvander@147: } dvander@68: bool isNativeVariadic() { dvander@68: assert(isNative()); dvander@68: return variadicNative_; dvander@0: } dvander@11: PrimitiveType primitive() { dvander@0: assert(isPrimitive()); dvander@13: return primitive_; dvander@0: } dvander@145: PrimitiveType pod() { dvander@145: assert(isPrimitive() || isEnum()); dvander@145: return isPrimitive() dvander@152: ? (primitive() == PrimitiveType_Bool) dvander@152: ? PrimitiveType_Int32 dvander@152: : primitive() dvander@145: : PrimitiveType_Int32; dvander@145: } dvander@11: Type *contained() { dvander@14: assert(isArray() || isReference()); dvander@13: return Type::cast(contained_); dvander@0: } dvander@11: int elements() { dvander@0: assert(isArray()); dvander@13: return elements_; dvander@0: } dvander@11: unsigned levels() { dvander@0: assert(isArray()); dvander@13: return levels_; dvander@0: } dvander@11: Type *innermost() { dvander@0: assert(isArray()); dvander@0: Type *temp = contained(); dvander@0: while (temp->isArray()) dvander@0: temp = temp->contained(); dvander@0: return temp; dvander@0: } dvander@11: bool isFloat() { dvander@4: return isPrimitive() && primitive() == PrimitiveType_Float; dvander@4: } dvander@20: bool isInt32() { dvander@4: return isPrimitive() && primitive() == PrimitiveType_Int32; dvander@4: } dvander@145: bool isInt32OrEnum() { dvander@145: return isInt32() || isEnum(); dvander@145: } dvander@147: bool isBool() { dvander@147: return isPrimitive() && primitive() == PrimitiveType_Bool; dvander@147: } dvander@21: bool isCharArray() { dvander@21: return isArray() && dvander@21: contained()->isPrimitive() && dvander@21: contained()->primitive() == PrimitiveType_Char; dvander@21: } dvander@14: Type *returnType() { dvander@14: assert(isFunction()); dvander@14: return returnType_; dvander@14: } dvander@14: FixedArray *parameters() { dvander@14: assert(isFunction()); dvander@14: return parameters_; dvander@14: } dvander@25: Type *parameterAt(size_t i) { dvander@25: return Type::cast(parameters()->at(i)); dvander@25: } dvander@47: bool isTraceable() { dvander@47: return !isPrimitive(); dvander@47: } dvander@67: bool isConst() { dvander@67: assert(kind() == PRIMITIVE || kind() == ARRAY || kind() == REFERENCE); dvander@67: return const_; dvander@67: } dvander@145: bool isEnum() { dvander@145: return kind() == ENUM; dvander@145: } dvander@145: dvander@145: String *name() { dvander@147: assert(isEnum() || isStruct()); dvander@145: return name_; dvander@145: } dvander@148: FixedArray *fields() { dvander@148: assert(isStruct()); dvander@148: return fields_; dvander@148: } dvander@148: Descriptor *lookupField(Handle name, unsigned *index); dvander@0: dvander@147: // Objects of this type can be created with this cached map. dvander@147: Map *newMap() { dvander@147: assert(isStruct()); dvander@147: return newMap_; dvander@147: } dvander@147: dvander@44: // GC Descriptor. dvander@44: static inline size_t offsetOfContained() { danderson@91: return OFFSETOF(Type, contained_); dvander@44: } dvander@44: static inline size_t offsetOfReturnType() { danderson@91: return OFFSETOF(Type, returnType_); dvander@44: } dvander@44: static inline size_t offsetOfParameters() { danderson@91: return OFFSETOF(Type, parameters_); dvander@44: } dvander@145: static inline size_t offsetOfName() { dvander@145: return OFFSETOF(Type, name_); dvander@54: } dvander@146: static inline size_t offsetOfFields() { dvander@146: return OFFSETOF(Type, fields_); dvander@146: } dvander@147: static inline size_t offsetOfNewMap() { dvander@147: return OFFSETOF(Type, newMap_); dvander@147: } dvander@44: // End GC Descriptor. dvander@44: dvander@0: private: dvander@13: Kind kind_; dvander@13: PrimitiveType primitive_; dvander@0: dvander@67: // Primitives, arrays, and references. dvander@67: bool const_; dvander@67: dvander@11: // Arrays only. dvander@13: int32 elements_; dvander@13: unsigned levels_; dvander@14: dvander@14: // Arrays and references only. dvander@13: Barriered contained_; dvander@14: dvander@14: // Functions only. dvander@14: Barriered returnType_; dvander@14: Barriered parameters_; dvander@68: bool variadicNative_; dvander@145: dvander@146: // Enums and structs only. dvander@145: Barriered name_; dvander@146: dvander@146: // Structs only. dvander@146: Barriered fields_; dvander@147: Barriered newMap_; dvander@0: }; dvander@0: dvander@2: class BoxedPrimitive dvander@2: { dvander@2: PrimitiveType type_; dvander@2: union { dvander@2: int i_; dvander@2: }; dvander@2: dvander@2: public: dvander@2: static BoxedPrimitive Int(int i) { dvander@2: BoxedPrimitive b; dvander@2: b.type_ = PrimitiveType_Int32; dvander@2: b.i_ = i; dvander@2: return b; dvander@2: } dvander@2: dvander@2: PrimitiveType type() const { dvander@2: return type_; dvander@2: } dvander@2: int toInt() const { dvander@2: assert(type() == PrimitiveType_Int32); dvander@2: return i_; dvander@2: } dvander@2: }; dvander@2: dvander@0: } dvander@0: dvander@0: #endif // _include_jc_types_h_