// | |
// Copyright (c) 2002-2013 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 "compiler/BaseTypes.h" | |
#include "compiler/Common.h" | |
#include "compiler/debug.h" | |
#include <algorithm> | |
class TType; | |
struct TPublicType; | |
// | |
// Need to have association of line numbers to types in a list for building structs. | |
// | |
struct TTypeLine { | |
TType* type; | |
int line; | |
}; | |
typedef TVector<TTypeLine> TTypeList; | |
inline TTypeList* NewPoolTTypeList() | |
{ | |
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); | |
return new(memory) TTypeList; | |
} | |
// | |
// Base class for things that have a type. | |
// | |
class TType | |
{ | |
public: | |
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) | |
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), | |
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) | |
{ | |
} | |
explicit TType(const TPublicType &p); | |
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : | |
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), | |
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) | |
{ | |
typeName = NewPoolTString(n.c_str()); | |
} | |
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 | |
int getObjectSize() const | |
{ | |
if(isArray()) | |
{ | |
return getElementSize() * std::max(getArraySize(), getMaxArraySize()); | |
} | |
else | |
{ | |
return getElementSize(); | |
} | |
} | |
int getElementSize() const | |
{ | |
if(getBasicType() == EbtStruct) | |
{ | |
return getStructSize(); | |
} | |
else if(matrix) | |
{ | |
return size * size; | |
} | |
else // Vector or scalar | |
{ | |
return size; | |
} | |
} | |
int elementRegisterCount() const | |
{ | |
TTypeList *structure = getStruct(); | |
if(structure) | |
{ | |
int registerCount = 0; | |
for(size_t i = 0; i < structure->size(); i++) | |
{ | |
registerCount += (*structure)[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; } | |
int getMaxArraySize () const { return maxArraySize; } | |
void setMaxArraySize (int s) { maxArraySize = s; } | |
void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } | |
void setArrayInformationType(TType* t) { arrayInformationType = t; } | |
TType* getArrayInformationType() const { return arrayInformationType; } | |
bool isVector() const { return size > 1 && !matrix; } | |
bool isScalar() const { return size == 1 && !matrix && !structure; } | |
bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register | |
bool isStruct() const { return structure != 0; } | |
TTypeList* getStruct() const { return structure; } | |
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } | |
const TString& getTypeName() const | |
{ | |
assert(typeName); | |
return *typeName; | |
} | |
void setTypeName(const TString& n) | |
{ | |
typeName = NewPoolTString(n.c_str()); | |
} | |
bool isField() const { return fieldName != 0; } | |
const TString& getFieldName() const | |
{ | |
assert(fieldName); | |
return *fieldName; | |
} | |
void setFieldName(const TString& n) | |
{ | |
fieldName = NewPoolTString(n.c_str()); | |
} | |
TString& getMangledName() { | |
if (!mangled) { | |
mangled = NewPoolTString(""); | |
buildMangledName(*mangled); | |
*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 deepestStructNesting; } | |
bool isStructureContainingArrays() const; | |
protected: | |
void buildMangledName(TString&); | |
int getStructSize() const; | |
void computeDeepestStructNesting(); | |
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; | |
int maxArraySize; | |
TType* arrayInformationType; | |
TTypeList* structure; // 0 unless this is a struct | |
mutable int structureSize; | |
int deepestStructNesting; | |
TString *fieldName; // for structure field names | |
TString *mangled; | |
TString *typeName; // for structure field type name | |
}; | |
// | |
// 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; | |
int line; | |
void setBasic(TBasicType bt, TQualifier q, int ln = 0) | |
{ | |
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_ |