blob: bf955835d1d27fbeb41657069d6323846cc9e1b5 [file] [log] [blame]
//
// 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(GlobalPoolAllocator);
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<TField*> TFieldList;
inline TFieldList* NewPoolTFieldList()
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TFieldList));
return new(memory) TFieldList;
}
class TStructure
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
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(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), 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;
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_