// // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #ifndef _TYPES_INCLUDED #define _TYPES_INCLUDED #include "common/angleutils.h" #include "compiler/BaseTypes.h" #include "compiler/Common.h" #include "compiler/debug.h" struct TPublicType; class TType; class TField { public: POOL_ALLOCATOR_NEW_DELETE(); TField(TType* type, TString* name) : mType(type), mName(name) {} // TODO(alokp): We should only return const type. // Fix it by tweaking grammar. TType* type() { return mType; } const TType* type() const { return mType; } const TString& name() const { return *mName; } private: DISALLOW_COPY_AND_ASSIGN(TField); TType* mType; TString* mName; }; typedef TVector TFieldList; inline TFieldList* NewPoolTFieldList() { void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); return new(memory) TFieldList; } class TStructure { public: POOL_ALLOCATOR_NEW_DELETE(); TStructure(TString* name, TFieldList* fields) : mName(name), mFields(fields), mObjectSize(0), mDeepestNesting(0) { } const TString& name() const { return *mName; } const TFieldList& fields() const { return *mFields; } const TString& mangledName() const { if (mMangledName.empty()) mMangledName = buildMangledName(); return mMangledName; } size_t objectSize() const { if (mObjectSize == 0) mObjectSize = calculateObjectSize(); return mObjectSize; }; int deepestNesting() const { if (mDeepestNesting == 0) mDeepestNesting = calculateDeepestNesting(); return mDeepestNesting; } bool containsArrays() const; private: DISALLOW_COPY_AND_ASSIGN(TStructure); TString buildMangledName() const; size_t calculateObjectSize() const; int calculateDeepestNesting() const; TString* mName; TFieldList* mFields; mutable TString mMangledName; mutable size_t mObjectSize; mutable int mDeepestNesting; }; // // Base class for things that have a type. // class TType { public: POOL_ALLOCATOR_NEW_DELETE(); TType() {} TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) { } explicit TType(const TPublicType &p); TType(TStructure* userDef, TPrecision p = EbpUndefined) : type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) { } TBasicType getBasicType() const { return type; } void setBasicType(TBasicType t) { type = t; } TPrecision getPrecision() const { return precision; } void setPrecision(TPrecision p) { precision = p; } TQualifier getQualifier() const { return qualifier; } void setQualifier(TQualifier q) { qualifier = q; } // One-dimensional size of single instance type int getNominalSize() const { return size; } void setNominalSize(int s) { size = s; } // Full size of single instance of type size_t getObjectSize() const; int elementRegisterCount() const { if (structure) { const TFieldList &fields = getStruct()->fields(); int registerCount = 0; for (size_t i = 0; i < fields.size(); i++) { registerCount += fields[i]->type()->totalRegisterCount(); } return registerCount; } else if (isMatrix()) { return getNominalSize(); } else { return 1; } } int totalRegisterCount() const { if (array) { return arraySize * elementRegisterCount(); } else { return elementRegisterCount(); } } bool isMatrix() const { return matrix ? true : false; } void setMatrix(bool m) { matrix = m; } bool isArray() const { return array ? true : false; } int getArraySize() const { return arraySize; } void setArraySize(int s) { array = true; arraySize = s; } void clearArrayness() { array = false; arraySize = 0; } bool isVector() const { return size > 1 && !matrix; } bool isScalar() const { return size == 1 && !matrix && !structure; } TStructure* getStruct() const { return structure; } void setStruct(TStructure* s) { structure = s; } const TString& getMangledName() const { if (mangled.empty()) { mangled = buildMangledName(); mangled += ';'; } return mangled; } bool sameElementType(const TType& right) const { return type == right.type && size == right.size && matrix == right.matrix && structure == right.structure; } bool operator==(const TType& right) const { return type == right.type && size == right.size && matrix == right.matrix && array == right.array && (!array || arraySize == right.arraySize) && structure == right.structure; // don't check the qualifier, it's not ever what's being sought after } bool operator!=(const TType& right) const { return !operator==(right); } bool operator<(const TType& right) const { if (type != right.type) return type < right.type; if (size != right.size) return size < right.size; if (matrix != right.matrix) return matrix < right.matrix; if (array != right.array) return array < right.array; if (arraySize != right.arraySize) return arraySize < right.arraySize; if (structure != right.structure) return structure < right.structure; return false; } const char* getBasicString() const { return ::getBasicString(type); } const char* getPrecisionString() const { return ::getPrecisionString(precision); } const char* getQualifierString() const { return ::getQualifierString(qualifier); } TString getCompleteString() const; // If this type is a struct, returns the deepest struct nesting of // any field in the struct. For example: // struct nesting1 { // vec4 position; // }; // struct nesting2 { // nesting1 field1; // vec4 field2; // }; // For type "nesting2", this method would return 2 -- the number // of structures through which indirection must occur to reach the // deepest field (nesting2.field1.position). int getDeepestStructNesting() const { return structure ? structure->deepestNesting() : 0; } bool isStructureContainingArrays() const { return structure ? structure->containsArrays() : false; } private: TString buildMangledName() const; TBasicType type : 6; TPrecision precision; TQualifier qualifier : 7; int size : 8; // size of vector or matrix, not size of array unsigned int matrix : 1; unsigned int array : 1; int arraySize; TStructure* structure; // 0 unless this is a struct mutable TString mangled; }; // // This is a workaround for a problem with the yacc stack, It can't have // types that it thinks have non-trivial constructors. It should // just be used while recognizing the grammar, not anything else. Pointers // could be used, but also trying to avoid lots of memory management overhead. // // Not as bad as it looks, there is no actual assumption that the fields // match up or are name the same or anything like that. // struct TPublicType { TBasicType type; TQualifier qualifier; TPrecision precision; int size; // size of vector or matrix, not size of array bool matrix; bool array; int arraySize; TType* userDef; TSourceLoc line; void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) { type = bt; qualifier = q; precision = EbpUndefined; size = 1; matrix = false; array = false; arraySize = 0; userDef = 0; line = ln; } void setAggregate(int s, bool m = false) { size = s; matrix = m; } void setArray(bool a, int s = 0) { array = a; arraySize = s; } bool isStructureContainingArrays() const { if (!userDef) { return false; } return userDef->isStructureContainingArrays(); } }; #endif // _TYPES_INCLUDED_