1.1 --- a/src/Types.h Mon Dec 24 16:43:22 2012 -0800
1.2 +++ b/src/Types.h Tue Dec 25 16:32:06 2012 -0800
1.3 @@ -1,484 +1,535 @@
1.4 -/* vim: set ts=4 sw=4 tw=99 et:
1.5 - *
1.6 - * Copyright (C) 2012 David Anderson
1.7 - *
1.8 - * This file is part of JITCraft.
1.9 - *
1.10 - * JITCraft is free software: you can redistribute it and/or modify it under
1.11 - * the terms of the GNU General Public License as published by the Free
1.12 - * Software Foundation, either version 3 of the License, or (at your option)
1.13 - * any later version.
1.14 - *
1.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License along with
1.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
1.21 - */
1.22 -#ifndef _include_jc_types_h_
1.23 -#define _include_jc_types_h_
1.24 -
1.25 -#include "Heap.h"
1.26 -#include "Barriers.h"
1.27 -#include "FixedArray.h"
1.28 -#include "compiler/Token.h"
1.29 -
1.30 -namespace ke {
1.31 -
1.32 -class String;
1.33 -class Descriptor;
1.34 -class StructMap;
1.35 -class ArrayMap;
1.36 -
1.37 -#define MAX_ARRAY_DEPTH 5
1.38 -
1.39 -enum PrimitiveType
1.40 -{
1.41 - // A boolean type semantically represents 0 or 1. As an optimization, its
1.42 - // internal storage type is the same as int32, and any non-zero value
1.43 - // compares positively to "true".
1.44 - PrimitiveType_Bool,
1.45 -
1.46 - // A character is an arbitrary 8-bit value. Characters are not supported
1.47 - // as a normal storage class; they may only be used for arrays. When read
1.48 - // from an array, they are immediately sign extended to 32 bits. Integers
1.49 - // stored into an char array are truncated to 8 bits.
1.50 - PrimitiveType_Char, // signed, 8-bit character
1.51 -
1.52 - // Enumerations and untyped variables are stored as signed, 32-bit integers.
1.53 - PrimitiveType_Int32,
1.54 -
1.55 - // Floating point values are 32-bit IEEE-754 floats. This is required ro
1.56 - // SourcePawn 1 compatibility.
1.57 - PrimitiveType_Float,
1.58 -
1.59 - // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
1.60 - // on 64-bit systems), and does not exist in language semantics.
1.61 - PrimitiveType_Native,
1.62 -
1.63 - PrimitiveTypes_Total
1.64 -};
1.65 -
1.66 -class Type : public Object
1.67 -{
1.68 - protected:
1.69 - enum Kind {
1.70 - // A primitive is a plain-old-data type.
1.71 - PRIMITIVE,
1.72 -
1.73 - // Void is an internal type used to specify that a function returns no
1.74 - // value.
1.75 - VOID,
1.76 -
1.77 - // Enums are plain-old-data with int32 storage. They allow for extra
1.78 - // type checking that would not be possible with integers.
1.79 - ENUM,
1.80 -
1.81 - // Unchecked is a magic type that has implicit, bitwise coercion to
1.82 - // int32, float, bool, or an enum.
1.83 - UNCHECKED,
1.84 -
1.85 - // ------ Add traceable types below -------
1.86 -
1.87 - // An immutable type that is a primitive in terms of language
1.88 - // semantics, but gets a special type here to make internal
1.89 - // logic easier.
1.90 - STRING,
1.91 -
1.92 - // An array is a fixed-length vector of any other type.
1.93 - ARRAY,
1.94 - EXTERNAL_ARRAY,
1.95 -
1.96 - // A reference type may only be specified on parameters, and
1.97 - // references may only be computed to primitives or enums.
1.98 - REFERENCE,
1.99 -
1.100 - // A function type encapsulates a function signature.
1.101 - FUNCTION,
1.102 -
1.103 - // Structs are composite records that may contain primitives, arrays,
1.104 - // functions, enums, and other structs.
1.105 - STRUCT
1.106 - };
1.107 -
1.108 - private:
1.109 - Kind kind() {
1.110 - return kind_;
1.111 - }
1.112 -
1.113 - public:
1.114 - static Type *NewVoid(Zone *zone);
1.115 - static Type *NewUnchecked(Zone *zone);
1.116 - static Type *NewPrimitive(Zone *zone, PrimitiveType type);
1.117 - static Type *NewString(Zone *zone);
1.118 -
1.119 - static Type *cast(Object *obj) {
1.120 - assert(!obj ||
1.121 - obj->is(MapKind_Type) ||
1.122 - obj->is(MapKind_FunctionType) ||
1.123 - obj->is(MapKind_StructType) ||
1.124 - obj->is(MapKind_ArrayType) ||
1.125 - obj->is(MapKind_ReferenceType) ||
1.126 - obj->is(MapKind_EnumType));
1.127 - return (Type *)obj;
1.128 - }
1.129 -
1.130 - bool isPrimitive() {
1.131 - return kind() == PRIMITIVE;
1.132 - }
1.133 - bool isArray() {
1.134 - return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
1.135 - }
1.136 - bool isReference() {
1.137 - return kind() == REFERENCE;
1.138 - }
1.139 - bool isFunction() {
1.140 - return kind() == FUNCTION;
1.141 - }
1.142 - bool isVoid() {
1.143 - return kind() == VOID;
1.144 - }
1.145 - bool isUnchecked() {
1.146 - return kind() == UNCHECKED;
1.147 - }
1.148 - bool isStruct() {
1.149 - return kind() == STRUCT;
1.150 - }
1.151 - PrimitiveType primitive() {
1.152 - assert(isPrimitive());
1.153 - return primitive_;
1.154 - }
1.155 - bool isPod() {
1.156 - return (isPrimitive() && !isString()) || isEnum() || isUnchecked();
1.157 - }
1.158 - PrimitiveType pod() {
1.159 - assert(isPod());
1.160 - return isPrimitive()
1.161 - ? (primitive() == PrimitiveType_Bool)
1.162 - ? PrimitiveType_Int32
1.163 - : primitive()
1.164 - : PrimitiveType_Int32;
1.165 - }
1.166 - bool isChar() {
1.167 - return isPrimitive() && primitive() == PrimitiveType_Char;
1.168 - }
1.169 - bool isFloat() {
1.170 - return isPrimitive() && primitive() == PrimitiveType_Float;
1.171 - }
1.172 - bool isInt32() {
1.173 - return isPrimitive() && primitive() == PrimitiveType_Int32;
1.174 - }
1.175 - bool isInt32OrEnum() {
1.176 - return isInt32() || isEnum();
1.177 - }
1.178 - bool isBool() {
1.179 - return isPrimitive() && primitive() == PrimitiveType_Bool;
1.180 - }
1.181 - bool isString() {
1.182 - return kind() == STRING;
1.183 - }
1.184 - bool isExternalArray() {
1.185 - return kind() == EXTERNAL_ARRAY;
1.186 - }
1.187 - bool isTraceable() {
1.188 - return kind_ >= STRING;
1.189 - }
1.190 - bool isConst() {
1.191 - assert(isPrimitive() ||
1.192 - isArray() ||
1.193 - isReference());
1.194 - return const_;
1.195 - }
1.196 - bool isEnum() {
1.197 - return kind() == ENUM;
1.198 - }
1.199 -
1.200 - protected:
1.201 - Kind kind_;
1.202 - PrimitiveType primitive_;
1.203 -
1.204 - // Primitives, arrays, and references.
1.205 - bool const_;
1.206 -};
1.207 -
1.208 -class EnumType : public Type
1.209 -{
1.210 - public:
1.211 - static EnumType *New(Zone *Zone, Handle<String> name);
1.212 -
1.213 - String *name() {
1.214 - return name_;
1.215 - }
1.216 -
1.217 - // GC Descriptor.
1.218 - static inline size_t offsetOfName() {
1.219 - return OFFSETOF(EnumType, name_);
1.220 - }
1.221 - // End GC Descriptor.
1.222 -
1.223 - static EnumType *cast(Object *obj) {
1.224 - assert(!obj || obj->is(MapKind_EnumType));
1.225 - return (EnumType *)obj;
1.226 - }
1.227 -
1.228 - private:
1.229 - Barriered<String> name_;
1.230 -};
1.231 -
1.232 -class ReferenceType : public Type
1.233 -{
1.234 - public:
1.235 - static ReferenceType *New(Zone *zone, Handle<Type> contained);
1.236 -
1.237 - Type *contained() {
1.238 - return contained_;
1.239 - }
1.240 -
1.241 - // GC Descriptor.
1.242 - static inline size_t offsetOfContained() {
1.243 - return OFFSETOF(ReferenceType, contained_);
1.244 - }
1.245 - // End GC Descriptor.
1.246 -
1.247 - static ReferenceType *cast(Object *obj) {
1.248 - assert(!obj || obj->is(MapKind_ReferenceType));
1.249 - return (ReferenceType *)obj;
1.250 - }
1.251 -
1.252 - private:
1.253 - Barriered<Type> contained_;
1.254 -};
1.255 -
1.256 -class ArrayType : public Type
1.257 -{
1.258 - public:
1.259 - static const int DYNAMIC_ARRAY_SIZE = -1;
1.260 -
1.261 - static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
1.262 - static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
1.263 -
1.264 - Type *innermost() {
1.265 - Type *temp = contained();
1.266 - while (temp->isArray())
1.267 - temp = ArrayType::cast(temp)->contained();
1.268 - return temp;
1.269 - }
1.270 -
1.271 - Type *contained() {
1.272 - return contained_;
1.273 - }
1.274 - bool isFixedLength() {
1.275 - return elements_ > 0;
1.276 - }
1.277 - bool isCharArray() {
1.278 - return contained()->isPrimitive() &&
1.279 - contained()->primitive() == PrimitiveType_Char;
1.280 - }
1.281 - unsigned fixedLength() {
1.282 - assert(isFixedLength());
1.283 - return elements_;
1.284 - }
1.285 - unsigned levels() {
1.286 - return levels_;
1.287 - }
1.288 - bool hasInlineElements() {
1.289 - // We don't allocate traceable elements inline, since there's no
1.290 - // point to the optimization; we're going to be allocating lots of
1.291 - // objects anyway (in theory).
1.292 - return isFixedLength() && !contained()->isTraceable();
1.293 - }
1.294 -
1.295 - // Arrays of this type can be created with this cached map.
1.296 - ArrayMap *newMap() {
1.297 - return newMap_;
1.298 - }
1.299 - void setNewMap(ArrayMap *map) {
1.300 - assert(!newMap());
1.301 - newMap_ = map;
1.302 - }
1.303 -
1.304 - // GC Descriptor.
1.305 - static inline size_t offsetOfContained() {
1.306 - return OFFSETOF(ArrayType, contained_);
1.307 - }
1.308 - static inline size_t offsetOfNewMap() {
1.309 - return OFFSETOF(ArrayType, newMap_);
1.310 - }
1.311 - // End GC Descriptor.
1.312 -
1.313 - static ArrayType *cast(Object *obj) {
1.314 - assert(!obj || obj->is(MapKind_ArrayType));
1.315 - return (ArrayType *)obj;
1.316 - }
1.317 -
1.318 - private:
1.319 - int32 elements_;
1.320 - unsigned levels_;
1.321 - Barriered<Type> contained_;
1.322 - Barriered<ArrayMap> newMap_;
1.323 -};
1.324 -
1.325 -class StructType : public Type
1.326 -{
1.327 - public:
1.328 - static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
1.329 -
1.330 - FixedArray *fields() {
1.331 - assert(isStruct());
1.332 - return fields_;
1.333 - }
1.334 - Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
1.335 -
1.336 - // Objects of this type can be created with this cached map.
1.337 - StructMap *newMap() {
1.338 - return newMap_;
1.339 - }
1.340 - void setNewMap(StructMap *map) {
1.341 - assert(!newMap());
1.342 - newMap_ = map;
1.343 - }
1.344 -
1.345 - String *name() {
1.346 - return name_;
1.347 - }
1.348 -
1.349 - // GC Descriptor.
1.350 - static inline size_t offsetOfFields() {
1.351 - return OFFSETOF(StructType, fields_);
1.352 - }
1.353 - static inline size_t offsetOfNewMap() {
1.354 - return OFFSETOF(StructType, newMap_);
1.355 - }
1.356 - static inline size_t offsetOfName() {
1.357 - return OFFSETOF(StructType, name_);
1.358 - }
1.359 - // End GC Descriptor.
1.360 -
1.361 - static StructType *cast(Object *obj) {
1.362 - assert(!obj || obj->is(MapKind_StructType));
1.363 - return (StructType *)obj;
1.364 - }
1.365 -
1.366 - private:
1.367 - // Structs only.
1.368 - Barriered<FixedArray> fields_;
1.369 - Barriered<StructMap> newMap_;
1.370 - Barriered<String> name_;
1.371 -};
1.372 -
1.373 -class FunctionType : public Type
1.374 -{
1.375 - public:
1.376 - static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
1.377 -
1.378 - Type *parameterAt(size_t i) {
1.379 - return Type::cast(parameters()->at(i));
1.380 - }
1.381 - Type *returnType() {
1.382 - assert(isFunction());
1.383 - return returnType_;
1.384 - }
1.385 - FixedArray *parameters() {
1.386 - assert(isFunction());
1.387 - return parameters_;
1.388 - }
1.389 - FixedArray *defaults() {
1.390 - assert(isFunction());
1.391 - return defaults_;
1.392 - }
1.393 - bool isNative() {
1.394 - return token_ == TOK_NATIVE;
1.395 - }
1.396 - bool isForward() {
1.397 - return token_ == TOK_FORWARD;
1.398 - }
1.399 - bool isNativeVariadic() {
1.400 - assert(isNative());
1.401 - return variadicNative_;
1.402 - }
1.403 - void setReturnType(Handle<Type> returnType) {
1.404 - assert(!returnType_);
1.405 - returnType_ = returnType;
1.406 - }
1.407 - void setParameterTypes(Handle<FixedArray> types) {
1.408 - assert(!parameters_);
1.409 - parameters_ = types;
1.410 - }
1.411 - TokenKind token() {
1.412 - return token_;
1.413 - }
1.414 - String *name() {
1.415 - return name_;
1.416 - }
1.417 -
1.418 - // GC Descriptor.
1.419 - static inline size_t offsetOfReturnType() {
1.420 - return OFFSETOF(FunctionType, returnType_);
1.421 - }
1.422 - static inline size_t offsetOfParameters() {
1.423 - return OFFSETOF(FunctionType, parameters_);
1.424 - }
1.425 - static inline size_t offsetOfDefaults() {
1.426 - return OFFSETOF(FunctionType, defaults_);
1.427 - }
1.428 - static inline size_t offsetOfName() {
1.429 - return OFFSETOF(FunctionType, name_);
1.430 - }
1.431 - // End GC Descriptor.
1.432 -
1.433 - static FunctionType *cast(Object *obj) {
1.434 - assert(!obj || obj->is(MapKind_FunctionType));
1.435 - return (FunctionType *)obj;
1.436 - }
1.437 -
1.438 - private:
1.439 - // Functions only.
1.440 - Barriered<Type> returnType_;
1.441 - Barriered<FixedArray> parameters_;
1.442 - Barriered<FixedArray> defaults_;
1.443 - Barriered<String> name_;
1.444 - TokenKind token_;
1.445 - bool variadicNative_;
1.446 -};
1.447 -
1.448 -class BoxedPrimitive
1.449 -{
1.450 - PrimitiveType type_;
1.451 - union {
1.452 - int i_;
1.453 - float f_;
1.454 - };
1.455 -
1.456 - public:
1.457 - static BoxedPrimitive Int(int i) {
1.458 - BoxedPrimitive b;
1.459 - b.type_ = PrimitiveType_Int32;
1.460 - b.i_ = i;
1.461 - return b;
1.462 - }
1.463 - static BoxedPrimitive Float(float f) {
1.464 - BoxedPrimitive b;
1.465 - b.type_ = PrimitiveType_Float;
1.466 - b.f_ = f;
1.467 - return b;
1.468 - }
1.469 -
1.470 - PrimitiveType type() const {
1.471 - return type_;
1.472 - }
1.473 - int toInt() const {
1.474 - assert(type() == PrimitiveType_Int32);
1.475 - return i_;
1.476 - }
1.477 - float toFloat() const {
1.478 - assert(type() == PrimitiveType_Float);
1.479 - return f_;
1.480 - }
1.481 -};
1.482 -
1.483 -const char *GetTypeName(Type *type);
1.484 -
1.485 -}
1.486 -
1.487 -#endif // _include_jc_types_h_
1.488 +/* vim: set ts=4 sw=4 tw=99 et:
1.489 + *
1.490 + * Copyright (C) 2012 David Anderson
1.491 + *
1.492 + * This file is part of JITCraft.
1.493 + *
1.494 + * JITCraft is free software: you can redistribute it and/or modify it under
1.495 + * the terms of the GNU General Public License as published by the Free
1.496 + * Software Foundation, either version 3 of the License, or (at your option)
1.497 + * any later version.
1.498 + *
1.499 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.500 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.501 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.502 + *
1.503 + * You should have received a copy of the GNU General Public License along with
1.504 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.505 + */
1.506 +#ifndef _include_jc_types_h_
1.507 +#define _include_jc_types_h_
1.508 +
1.509 +#include "Heap.h"
1.510 +#include "Barriers.h"
1.511 +#include "FixedArray.h"
1.512 +#include "compiler/Token.h"
1.513 +
1.514 +namespace ke {
1.515 +
1.516 +class String;
1.517 +class Descriptor;
1.518 +class StructMap;
1.519 +class ArrayMap;
1.520 +
1.521 +#define MAX_ARRAY_DEPTH 5
1.522 +
1.523 +enum PrimitiveType
1.524 +{
1.525 + // A boolean type semantically represents 0 or 1. As an optimization, its
1.526 + // internal storage type is the same as int32, and any non-zero value
1.527 + // compares positively to "true".
1.528 + PrimitiveType_Bool,
1.529 +
1.530 + // A character is an arbitrary 8-bit value. Characters are not supported
1.531 + // as a normal storage class; they may only be used for arrays. When read
1.532 + // from an array, they are immediately sign extended to 32 bits. Integers
1.533 + // stored into an char array are truncated to 8 bits.
1.534 + PrimitiveType_Char, // signed, 8-bit character
1.535 +
1.536 + // Enumerations and untyped variables are stored as signed, 32-bit integers.
1.537 + PrimitiveType_Int32,
1.538 +
1.539 + // Floating point values are 32-bit IEEE-754 floats. This is required ro
1.540 + // SourcePawn 1 compatibility.
1.541 + PrimitiveType_Float,
1.542 +
1.543 + // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
1.544 + // on 64-bit systems), and does not exist in language semantics.
1.545 + PrimitiveType_Native,
1.546 +
1.547 + PrimitiveTypes_Total
1.548 +};
1.549 +
1.550 +enum TypeQualifiers
1.551 +{
1.552 + TypeQual_None = 0,
1.553 +
1.554 + // Const qualifier that has not been determined yet.
1.555 + TypeQual_UnkConst = (1 << 0),
1.556 +
1.557 + // For simplification, SP2 differentiates between two meanings of const.
1.558 + // "StoreConst" means that the value itself may not be changed. For
1.559 + // example,
1.560 + // const a = 5;
1.561 + //
1.562 + // Specifies that the storage of "a" is immutable.
1.563 + //
1.564 + // In addition, "RefConst" means that the memory at a reference may not
1.565 + // be changed. For example,
1.566 + //
1.567 + // const char:text[] = "asdfasdfasdf";
1.568 + //
1.569 + // Specifies a readonly view of a character array, however, |text| itself
1.570 + // may be repointed to another readonly character array.
1.571 + //
1.572 + // The meaning of "const" is inferred based on the scope and type:
1.573 + //
1.574 + // +---------+---------+-------+
1.575 + // | Array | Struct | Other |
1.576 + // +---------------+---------+---------+-------+
1.577 + // | GLOBAL/STATIC | Ref|Str | Ref|Str | Str |
1.578 + // | LOCAL | Ref | Ref|Str | Str |
1.579 + // +---------------+---------+---------+-------+
1.580 + TypeQual_StoreConst = (1 << 1),
1.581 + TypeQual_RefConst = (1 << 2)
1.582 +};
1.583 +
1.584 +class Type : public Object
1.585 +{
1.586 + protected:
1.587 + enum Kind {
1.588 + // A primitive is a plain-old-data type.
1.589 + PRIMITIVE,
1.590 +
1.591 + // Void is an internal type used to specify that a function returns no
1.592 + // value.
1.593 + VOID,
1.594 +
1.595 + // Enums are plain-old-data with int32 storage. They allow for extra
1.596 + // type checking that would not be possible with integers.
1.597 + ENUM,
1.598 +
1.599 + // Unchecked is a magic type that has implicit, bitwise coercion to
1.600 + // int32, float, bool, or an enum.
1.601 + UNCHECKED,
1.602 +
1.603 + // ------ Add traceable types below -------
1.604 +
1.605 + // An immutable type that is a primitive in terms of language
1.606 + // semantics, but gets a special type here to make internal
1.607 + // logic easier.
1.608 + STRING,
1.609 +
1.610 + // An array is a fixed-length vector of any other type.
1.611 + ARRAY,
1.612 + EXTERNAL_ARRAY,
1.613 +
1.614 + // A reference type may only be specified on parameters, and
1.615 + // references may only be computed to primitives or enums.
1.616 + REFERENCE,
1.617 +
1.618 + // A function type encapsulates a function signature.
1.619 + FUNCTION,
1.620 +
1.621 + // Structs are composite records that may contain primitives, arrays,
1.622 + // functions, enums, and other structs.
1.623 + STRUCT,
1.624 +
1.625 + // Contains type qualifiers, and a back pointer to the actual
1.626 + // unqualified type.
1.627 + QUALTYPE
1.628 + };
1.629 +
1.630 + void init(Kind kind);
1.631 +
1.632 + private:
1.633 + Kind kind() {
1.634 + return root_->kind_;
1.635 + }
1.636 +
1.637 + public:
1.638 + static Type *NewVoid(Zone *zone);
1.639 + static Type *NewUnchecked(Zone *zone);
1.640 + static Type *NewPrimitive(Zone *zone, PrimitiveType type);
1.641 + static Type *NewString(Zone *zone);
1.642 +
1.643 + static Type *cast(Object *obj) {
1.644 + assert(!obj ||
1.645 + obj->is(MapKind_Type) ||
1.646 + obj->is(MapKind_FunctionType) ||
1.647 + obj->is(MapKind_StructType) ||
1.648 + obj->is(MapKind_ArrayType) ||
1.649 + obj->is(MapKind_ReferenceType) ||
1.650 + obj->is(MapKind_EnumType));
1.651 + return (Type *)obj;
1.652 + }
1.653 +
1.654 + bool isPrimitive() {
1.655 + return kind() == PRIMITIVE;
1.656 + }
1.657 + bool isArray() {
1.658 + return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
1.659 + }
1.660 + bool isReference() {
1.661 + return kind() == REFERENCE;
1.662 + }
1.663 + bool isFunction() {
1.664 + return kind() == FUNCTION;
1.665 + }
1.666 + bool isVoid() {
1.667 + return kind() == VOID;
1.668 + }
1.669 + bool isUnchecked() {
1.670 + return kind() == UNCHECKED;
1.671 + }
1.672 + bool isStruct() {
1.673 + return kind() == STRUCT;
1.674 + }
1.675 + PrimitiveType primitive() {
1.676 + assert(isPrimitive());
1.677 + return root_->primitive_;
1.678 + }
1.679 + bool isPod() {
1.680 + return (isPrimitive() && !isString()) || isEnum() || isUnchecked();
1.681 + }
1.682 + PrimitiveType pod() {
1.683 + assert(isPod());
1.684 + return isPrimitive()
1.685 + ? (primitive() == PrimitiveType_Bool)
1.686 + ? PrimitiveType_Int32
1.687 + : primitive()
1.688 + : PrimitiveType_Int32;
1.689 + }
1.690 + bool isChar() {
1.691 + return isPrimitive() && primitive() == PrimitiveType_Char;
1.692 + }
1.693 + bool isFloat() {
1.694 + return isPrimitive() && primitive() == PrimitiveType_Float;
1.695 + }
1.696 + bool isInt32() {
1.697 + return isPrimitive() && primitive() == PrimitiveType_Int32;
1.698 + }
1.699 + bool isInt32OrEnum() {
1.700 + return isInt32() || isEnum();
1.701 + }
1.702 + bool isBool() {
1.703 + return isPrimitive() && primitive() == PrimitiveType_Bool;
1.704 + }
1.705 + bool isString() {
1.706 + return kind() == STRING;
1.707 + }
1.708 + bool isExternalArray() {
1.709 + return kind() == EXTERNAL_ARRAY;
1.710 + }
1.711 + bool isTraceable() {
1.712 + return kind() >= STRING;
1.713 + }
1.714 + bool isEnum() {
1.715 + return kind() == ENUM;
1.716 + }
1.717 + bool hasTypeQualifiers() {
1.718 + return kind_ == QUALTYPE;
1.719 + }
1.720 +
1.721 + TypeQualifiers quals() {
1.722 + if (hasTypeQualifiers())
1.723 + return TypeQual_None;
1.724 + return quals_;
1.725 + }
1.726 +
1.727 + // GC Descriptor.
1.728 + static inline size_t offsetOfRoot() {
1.729 + return OFFSETOF(Type, root_);
1.730 + }
1.731 + // End GC Descriptor.
1.732 +
1.733 + protected:
1.734 + Kind kind_;
1.735 + PrimitiveType primitive_;
1.736 + TypeQualifiers quals_;
1.737 +
1.738 + // For unqualified types, this points to |this|. For qualified types, it
1.739 + // points to the unqualified original type.
1.740 + Barriered<Type> root_;
1.741 +};
1.742 +
1.743 +class EnumType : public Type
1.744 +{
1.745 + public:
1.746 + static EnumType *New(Zone *Zone, Handle<String> name);
1.747 +
1.748 + String *name() {
1.749 + return name_;
1.750 + }
1.751 +
1.752 + // GC Descriptor.
1.753 + static inline size_t offsetOfName() {
1.754 + return OFFSETOF(EnumType, name_);
1.755 + }
1.756 + // End GC Descriptor.
1.757 +
1.758 + static EnumType *cast(Object *obj) {
1.759 + assert(!obj || obj->is(MapKind_EnumType));
1.760 + return (EnumType *)obj;
1.761 + }
1.762 +
1.763 + private:
1.764 + Barriered<String> name_;
1.765 +};
1.766 +
1.767 +class ReferenceType : public Type
1.768 +{
1.769 + public:
1.770 + static ReferenceType *New(Zone *zone, Handle<Type> contained);
1.771 +
1.772 + Type *contained() {
1.773 + return contained_;
1.774 + }
1.775 +
1.776 + // GC Descriptor.
1.777 + static inline size_t offsetOfContained() {
1.778 + return OFFSETOF(ReferenceType, contained_);
1.779 + }
1.780 + // End GC Descriptor.
1.781 +
1.782 + static ReferenceType *cast(Object *obj) {
1.783 + assert(!obj || obj->is(MapKind_ReferenceType));
1.784 + return (ReferenceType *)obj;
1.785 + }
1.786 +
1.787 + private:
1.788 + Barriered<Type> contained_;
1.789 +};
1.790 +
1.791 +class ArrayType : public Type
1.792 +{
1.793 + public:
1.794 + static const int DYNAMIC_ARRAY_SIZE = -1;
1.795 +
1.796 + static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
1.797 + static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
1.798 +
1.799 + Type *innermost() {
1.800 + Type *temp = contained();
1.801 + while (temp->isArray())
1.802 + temp = ArrayType::cast(temp)->contained();
1.803 + return temp;
1.804 + }
1.805 +
1.806 + Type *contained() {
1.807 + return contained_;
1.808 + }
1.809 + bool isFixedLength() {
1.810 + return elements_ > 0;
1.811 + }
1.812 + bool isCharArray() {
1.813 + return contained()->isPrimitive() &&
1.814 + contained()->primitive() == PrimitiveType_Char;
1.815 + }
1.816 + unsigned fixedLength() {
1.817 + assert(isFixedLength());
1.818 + return elements_;
1.819 + }
1.820 + unsigned levels() {
1.821 + return levels_;
1.822 + }
1.823 + bool hasInlineElements() {
1.824 + // We don't allocate traceable elements inline, since there's no
1.825 + // point to the optimization; we're going to be allocating lots of
1.826 + // objects anyway (in theory).
1.827 + return isFixedLength() && !contained()->isTraceable();
1.828 + }
1.829 +
1.830 + // Arrays of this type can be created with this cached map.
1.831 + ArrayMap *newMap() {
1.832 + return newMap_;
1.833 + }
1.834 + void setNewMap(ArrayMap *map) {
1.835 + assert(!newMap());
1.836 + newMap_ = map;
1.837 + }
1.838 +
1.839 + // GC Descriptor.
1.840 + static inline size_t offsetOfContained() {
1.841 + return OFFSETOF(ArrayType, contained_);
1.842 + }
1.843 + static inline size_t offsetOfNewMap() {
1.844 + return OFFSETOF(ArrayType, newMap_);
1.845 + }
1.846 + // End GC Descriptor.
1.847 +
1.848 + static ArrayType *cast(Object *obj) {
1.849 + assert(!obj || obj->is(MapKind_ArrayType));
1.850 + return (ArrayType *)obj;
1.851 + }
1.852 +
1.853 + private:
1.854 + int32 elements_;
1.855 + unsigned levels_;
1.856 + Barriered<Type> contained_;
1.857 + Barriered<ArrayMap> newMap_;
1.858 +};
1.859 +
1.860 +class StructType : public Type
1.861 +{
1.862 + public:
1.863 + static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
1.864 +
1.865 + FixedArray *fields() {
1.866 + assert(isStruct());
1.867 + return fields_;
1.868 + }
1.869 + Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
1.870 +
1.871 + // Objects of this type can be created with this cached map.
1.872 + StructMap *newMap() {
1.873 + return newMap_;
1.874 + }
1.875 + void setNewMap(StructMap *map) {
1.876 + assert(!newMap());
1.877 + newMap_ = map;
1.878 + }
1.879 +
1.880 + String *name() {
1.881 + return name_;
1.882 + }
1.883 +
1.884 + // GC Descriptor.
1.885 + static inline size_t offsetOfFields() {
1.886 + return OFFSETOF(StructType, fields_);
1.887 + }
1.888 + static inline size_t offsetOfNewMap() {
1.889 + return OFFSETOF(StructType, newMap_);
1.890 + }
1.891 + static inline size_t offsetOfName() {
1.892 + return OFFSETOF(StructType, name_);
1.893 + }
1.894 + // End GC Descriptor.
1.895 +
1.896 + static StructType *cast(Object *obj) {
1.897 + assert(!obj || obj->is(MapKind_StructType));
1.898 + return (StructType *)obj;
1.899 + }
1.900 +
1.901 + private:
1.902 + // Structs only.
1.903 + Barriered<FixedArray> fields_;
1.904 + Barriered<StructMap> newMap_;
1.905 + Barriered<String> name_;
1.906 +};
1.907 +
1.908 +class FunctionType : public Type
1.909 +{
1.910 + public:
1.911 + static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
1.912 +
1.913 + Type *parameterAt(size_t i) {
1.914 + return Type::cast(parameters()->at(i));
1.915 + }
1.916 + Type *returnType() {
1.917 + assert(isFunction());
1.918 + return returnType_;
1.919 + }
1.920 + FixedArray *parameters() {
1.921 + assert(isFunction());
1.922 + return parameters_;
1.923 + }
1.924 + FixedArray *defaults() {
1.925 + assert(isFunction());
1.926 + return defaults_;
1.927 + }
1.928 + bool isNative() {
1.929 + return token_ == TOK_NATIVE;
1.930 + }
1.931 + bool isForward() {
1.932 + return token_ == TOK_FORWARD;
1.933 + }
1.934 + bool isNativeVariadic() {
1.935 + assert(isNative());
1.936 + return variadicNative_;
1.937 + }
1.938 + void setReturnType(Handle<Type> returnType) {
1.939 + assert(!returnType_);
1.940 + returnType_ = returnType;
1.941 + }
1.942 + void setParameterTypes(Handle<FixedArray> types) {
1.943 + assert(!parameters_);
1.944 + parameters_ = types;
1.945 + }
1.946 + TokenKind token() {
1.947 + return token_;
1.948 + }
1.949 + String *name() {
1.950 + return name_;
1.951 + }
1.952 +
1.953 + // GC Descriptor.
1.954 + static inline size_t offsetOfReturnType() {
1.955 + return OFFSETOF(FunctionType, returnType_);
1.956 + }
1.957 + static inline size_t offsetOfParameters() {
1.958 + return OFFSETOF(FunctionType, parameters_);
1.959 + }
1.960 + static inline size_t offsetOfDefaults() {
1.961 + return OFFSETOF(FunctionType, defaults_);
1.962 + }
1.963 + static inline size_t offsetOfName() {
1.964 + return OFFSETOF(FunctionType, name_);
1.965 + }
1.966 + // End GC Descriptor.
1.967 +
1.968 + static FunctionType *cast(Object *obj) {
1.969 + assert(!obj || obj->is(MapKind_FunctionType));
1.970 + return (FunctionType *)obj;
1.971 + }
1.972 +
1.973 + private:
1.974 + // Functions only.
1.975 + Barriered<Type> returnType_;
1.976 + Barriered<FixedArray> parameters_;
1.977 + Barriered<FixedArray> defaults_;
1.978 + Barriered<String> name_;
1.979 + TokenKind token_;
1.980 + bool variadicNative_;
1.981 +};
1.982 +
1.983 +class BoxedPrimitive
1.984 +{
1.985 + PrimitiveType type_;
1.986 + union {
1.987 + int i_;
1.988 + float f_;
1.989 + };
1.990 +
1.991 + public:
1.992 + static BoxedPrimitive Int(int i) {
1.993 + BoxedPrimitive b;
1.994 + b.type_ = PrimitiveType_Int32;
1.995 + b.i_ = i;
1.996 + return b;
1.997 + }
1.998 + static BoxedPrimitive Float(float f) {
1.999 + BoxedPrimitive b;
1.1000 + b.type_ = PrimitiveType_Float;
1.1001 + b.f_ = f;
1.1002 + return b;
1.1003 + }
1.1004 +
1.1005 + PrimitiveType type() const {
1.1006 + return type_;
1.1007 + }
1.1008 + int toInt() const {
1.1009 + assert(type() == PrimitiveType_Int32);
1.1010 + return i_;
1.1011 + }
1.1012 + float toFloat() const {
1.1013 + assert(type() == PrimitiveType_Float);
1.1014 + return f_;
1.1015 + }
1.1016 +};
1.1017 +
1.1018 +const char *GetTypeName(Type *type);
1.1019 +
1.1020 +}
1.1021 +
1.1022 +#endif // _include_jc_types_h_