Commit 71550929 by alokp@chromium.org

Simplified TType class by carving out TStructure and TField.

R=kbr@chromium.org Review URL: https://codereview.appspot.com/9866043 git-svn-id: https://angleproject.googlecode.com/svn/trunk@2423 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 41fc482d
......@@ -1019,23 +1019,22 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
{
const TTypeList* fields = leftNodeType.getStruct();
const TFieldList& fields = leftNodeType.getStruct()->fields();
size_t structSize = fields->size();
size_t structSize = fields.size();
size_t index = 0;
for (size_t j = 0; j < structSize; j++) {
size_t size = (*fields)[j]->getObjectSize();
size_t size = fields[j]->type()->getObjectSize();
for (size_t i = 0; i < size; i++) {
if ((*fields)[j]->getBasicType() == EbtStruct) {
if (!CompareStructure(*(*fields)[j], &rightUnionArray[index], &leftUnionArray[index]))
if (fields[j]->type()->getBasicType() == EbtStruct) {
if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
return false;
} else {
if (leftUnionArray[index] != rightUnionArray[index])
return false;
index++;
}
}
}
return true;
......
......@@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
out << type.getQualifierString() << " ";
// Declare the struct if we have not done so already.
if ((type.getBasicType() == EbtStruct) &&
(mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
{
out << "struct " << hashName(type.getTypeName()) << "{\n";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
{
const TType* fieldType = (*structure)[i];
ASSERT(fieldType != NULL);
if (writeVariablePrecision(fieldType->getPrecision()))
out << " ";
out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName());
if (fieldType->isArray())
out << arrayBrackets(*fieldType);
out << ";\n";
}
out << "}";
mDeclaredStructs.insert(type.getTypeName());
declareStruct(type.getStruct());
}
else
{
......@@ -138,15 +122,16 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
if (type.getBasicType() == EbtStruct)
{
out << hashName(type.getTypeName()) << "(";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
const TStructure* structure = type.getStruct();
out << hashName(structure->name()) << "(";
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TType* fieldType = (*structure)[i];
const TType* fieldType = fields[i]->type();
ASSERT(fieldType != NULL);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
if (i != structure->size() - 1) out << ", ";
if (i != fields.size() - 1) out << ", ";
}
out << ")";
}
......@@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
// Here we are writing out "foo.bar", where "foo" is struct
// and "bar" is field. In AST, it is represented as a binary
// node, where left child represents "foo" and right child "bar".
// The node itself represents ".". The struct field "bar" is
// actually stored as an index into TStructure::fields.
out << ".";
// TODO(alokp): ASSERT
TString fieldName = node->getType().getFieldName();
const TStructure* structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)];
const TType& structType = node->getLeft()->getType();
if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
TString fieldName = field->name();
if (!mSymbolTable.findBuiltIn(structure->name()))
fieldName = hashName(fieldName);
out << fieldName;
......@@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{
const TType& type = node->getType();
ASSERT(type.getBasicType() == EbtStruct);
out << hashName(type.getTypeName()) << "(";
out << hashName(type.getStruct()->name()) << "(";
}
else if (visit == InVisit)
{
......@@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
else
{
if (type.getBasicType() == EbtStruct)
out << hashName(type.getTypeName());
out << hashName(type.getStruct()->name());
else
out << type.getBasicString();
}
......@@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
return name;
return hashName(name);
}
bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
{
return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
}
void TOutputGLSLBase::declareStruct(const TStructure* structure)
{
TInfoSinkBase& out = objSink();
out << "struct " << hashName(structure->name()) << "{\n";
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField* field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
out << getTypeName(*field->type()) << " " << hashName(field->name());
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ";\n";
}
out << "}";
mDeclaredStructs.insert(structure->name());
}
......@@ -52,6 +52,9 @@ protected:
TString hashFunctionName(const TString& mangled_name);
private:
bool structDeclared(const TStructure* structure) const;
void declareStruct(const TStructure* structure);
TInfoSinkBase& mObjSink;
bool mDeclaringVariables;
......
......@@ -968,7 +968,10 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
const TStructure* structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)];
out << "." + decorateField(field->name(), node->getLeft()->getType());
return false;
}
......@@ -1037,18 +1040,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
out << "!(";
}
const TTypeList *fields = node->getLeft()->getType().getStruct();
const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
for (size_t i = 0; i < fields->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = (*fields)[i];
const TField *field = fields[i];
node->getLeft()->traverse(this);
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
node->getRight()->traverse(this);
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
out << "." + decorateField(field->name(), node->getLeft()->getType());
if (i < fields->size() - 1)
if (i < fields.size() - 1)
{
out << " && ";
}
......@@ -1299,7 +1302,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (variable->getType().getStruct())
{
addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
}
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
......@@ -1417,7 +1420,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (symbol->getType().getStruct())
{
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
}
out << argumentString(symbol);
......@@ -1666,8 +1669,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
outputTriplet(visit, "mat4(", ", ", ")");
break;
case EOpConstructStruct:
addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
......@@ -2229,22 +2232,23 @@ TString OutputHLSL::typeString(const TType &type)
{
if (type.getBasicType() == EbtStruct)
{
if (type.getTypeName() != "")
const TString& typeName = type.getStruct()->name();
if (typeName != "")
{
return structLookup(type.getTypeName());
return structLookup(typeName);
}
else // Nameless structure, define in place
{
const TTypeList &fields = *type.getStruct();
const TFieldList &fields = type.getStruct()->fields();
TString string = "struct\n"
"{\n";
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i];
const TField *field = fields[i];
string += " " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n";
string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
}
string += "} ";
......@@ -2364,13 +2368,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
structure += "struct " + decorate(name) + "\n"
"{\n";
const TTypeList &fields = *type.getStruct();
const TFieldList &fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i];
const TField *field = fields[i];
structure += " " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n";
structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
}
structure += "};\n";
......@@ -2382,7 +2386,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
for (unsigned int i = 0; i < fields.size(); i++)
{
ctorParameters.push_back(*fields[i]);
ctorParameters.push_back(*fields[i]->type());
}
}
else if (parameters)
......@@ -2555,17 +2559,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
if (type.getBasicType() == EbtStruct)
{
out << structLookup(type.getTypeName()) + "_ctor(";
out << structLookup(type.getStruct()->name()) + "_ctor(";
const TTypeList *structure = type.getStruct();
const TFieldList &fields = type.getStruct()->fields();
for (size_t i = 0; i < structure->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = (*structure)[i];
const TType *fieldType = fields[i]->type();
constUnion = writeConstantUnion(*fieldType, constUnion);
if (i != structure->size() - 1)
if (i != fields.size() - 1)
{
out << ", ";
}
......@@ -2676,7 +2680,7 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
TString OutputHLSL::decorateField(const TString &string, const TType &structure)
{
if (structure.getTypeName().compare(0, 3, "gl_") != 0)
if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
{
return decorate(string);
}
......
......@@ -535,7 +535,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* n
return true;
}
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
return true;
}
......@@ -658,9 +658,9 @@ bool TParseContext::containsSampler(TType& type)
return true;
if (type.getBasicType() == EbtStruct) {
TTypeList& structure = *type.getStruct();
for (unsigned int i = 0; i < structure.size(); ++i) {
if (containsSampler(*structure[i]))
const TFieldList& fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); ++i) {
if (containsSampler(*fields[i]->type()))
return true;
}
}
......@@ -1063,9 +1063,9 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
TIntermAggregate* aggrNode = node->getAsAggregate();
TTypeList::const_iterator memberTypes;
TFieldList::const_iterator memberFields;
if (op == EOpConstructStruct)
memberTypes = type->getStruct()->begin();
memberFields = type->getStruct()->fields().begin();
TType elementType = *type;
if (type->isArray())
......@@ -1087,7 +1087,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
else if (op == EOpConstructStruct)
newNode = constructStruct(node, *memberTypes, 1, node->getLine(), false);
newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
else
newNode = constructBuiltIn(type, op, node, node->getLine(), false);
......@@ -1118,7 +1118,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
else if (op == EOpConstructStruct)
newNode = constructStruct(*p, memberTypes[paramCount], paramCount+1, node->getLine(), true);
newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
else
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
......@@ -1370,14 +1370,14 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, co
//
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
{
const TTypeList* fields = node->getType().getStruct();
const TFieldList& fields = node->getType().getStruct()->fields();
size_t instanceSize = 0;
for (size_t index = 0; index < fields->size(); ++index) {
if ((*fields)[index]->getFieldName() == identifier) {
for (size_t index = 0; index < fields.size(); ++index) {
if (fields[index]->name() == identifier) {
break;
} else {
instanceSize += (*fields)[index]->getObjectSize();
instanceSize += fields[index]->type()->getObjectSize();
}
}
......@@ -1423,21 +1423,21 @@ const int kWebGLMaxStructNesting = 4;
} // namespace
bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TType& fieldType)
bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
{
if (!isWebGLBasedSpec(shaderSpec)) {
return false;
}
if (fieldType.getBasicType() != EbtStruct) {
if (field.type()->getBasicType() != EbtStruct) {
return false;
}
// We're already inside a structure definition at this point, so add
// one to the field's struct nesting.
if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
std::stringstream extraInfoStream;
extraInfoStream << "Reference of struct type " << fieldType.getTypeName()
extraInfoStream << "Reference of struct type " << field.name()
<< " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
std::string extraInfo = extraInfoStream.str();
error(line, "", "", extraInfo.c_str());
......
......@@ -124,7 +124,7 @@ struct TParseContext {
bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
void exitStructDeclaration();
bool structNestingErrorCheck(const TSourceLoc& line, const TType& fieldType);
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
};
int PaParseStrings(size_t count, const char* const string[], const int length[],
......
......@@ -20,44 +20,31 @@
#include <climits>
TType::TType(const TPublicType &p) :
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
{
if (p.userDef) {
if (p.userDef)
structure = p.userDef->getStruct();
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
computeDeepestStructNesting();
}
}
//
// Recursively generate mangled names.
//
void TType::buildMangledName(TString& mangledName)
TString TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
switch (type) {
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSamplerCube: mangledName += "sC"; break;
case EbtStruct:
mangledName += "struct-";
if (typeName)
mangledName += *typeName;
{// support MSVC++6.0
for (unsigned int i = 0; i < structure->size(); ++i) {
mangledName += '-';
(*structure)[i]->buildMangledName(mangledName);
}
}
default:
break;
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSamplerCube: mangledName += "sC"; break;
case EbtStruct: mangledName += structure->mangledName(); break;
default: break;
}
mangledName += static_cast<char>('0' + getNominalSize());
......@@ -68,6 +55,7 @@ void TType::buildMangledName(TString& mangledName)
mangledName += buf;
mangledName += ']';
}
return mangledName;
}
size_t TType::getObjectSize() const
......@@ -75,7 +63,7 @@ size_t TType::getObjectSize() const
size_t totalSize = 0;
if (getBasicType() == EbtStruct)
totalSize = getStructSize();
totalSize = structure->objectSize();
else if (matrix)
totalSize = size * size;
else
......@@ -92,57 +80,47 @@ size_t TType::getObjectSize() const
return totalSize;
}
size_t TType::getStructSize() const
bool TStructure::containsArrays() const
{
if (!getStruct()) {
assert(false && "Not a struct");
return 0;
}
if (structureSize == 0) {
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) {
size_t fieldSize = (*tl)->getObjectSize();
if (fieldSize > INT_MAX - structureSize)
structureSize = INT_MAX;
else
structureSize += fieldSize;
}
for (size_t i = 0; i < mFields->size(); ++i) {
const TType* fieldType = (*mFields)[i]->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
return structureSize;
return false;
}
void TType::computeDeepestStructNesting()
TString TStructure::buildMangledName() const
{
if (!getStruct()) {
return;
}
int maxNesting = 0;
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
maxNesting = std::max(maxNesting, (*tl)->getDeepestStructNesting());
TString mangledName("struct-");
mangledName += *mName;
for (size_t i = 0; i < mFields->size(); ++i) {
mangledName += '-';
mangledName += (*mFields)[i]->type()->getMangledName();
}
deepestStructNesting = 1 + maxNesting;
return mangledName;
}
bool TType::isStructureContainingArrays() const
size_t TStructure::calculateObjectSize() const
{
if (!structure)
{
return false;
size_t size = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
if (fieldSize > INT_MAX - size)
size = INT_MAX;
else
size += fieldSize;
}
return size;
}
for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
{
if ((*member)->isArray() ||
(*member)->isStructureContainingArrays())
{
return true;
}
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
return false;
return 1 + maxNesting;
}
//
......
......@@ -7,21 +7,86 @@
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
#include "common/angleutils.h"
#include "compiler/BaseTypes.h"
#include "compiler/Common.h"
#include "compiler/debug.h"
class TType;
struct TPublicType;
class TType;
typedef TVector<TType*> TTypeList;
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;
};
inline TTypeList* NewPoolTTypeList()
typedef TVector<TField*> TFieldList;
inline TFieldList* NewPoolTFieldList()
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
return new(memory) TTypeList;
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.
//
......@@ -31,16 +96,13 @@ 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), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(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),
structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
TType(TStructure* userDef, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef)
{
typeName = NewPoolTString(n.c_str());
}
TBasicType getBasicType() const { return type; }
......@@ -69,38 +131,15 @@ public:
bool isVector() const { return size > 1 && !matrix; }
bool isScalar() const { return size == 1 && !matrix && !structure; }
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());
}
TStructure* getStruct() const { return structure; }
void setStruct(TStructure* s) { structure = s; }
TString& getMangledName() {
if (!mangled) {
mangled = NewPoolTString("");
buildMangledName(*mangled);
*mangled += ';' ;
const TString& getMangledName() const {
if (mangled.empty()) {
mangled = buildMangledName();
mangled += ';';
}
return *mangled;
return mangled;
}
bool sameElementType(const TType& right) const {
......@@ -148,14 +187,16 @@ public:
// 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; }
int getDeepestStructNesting() const {
return structure ? structure->deepestNesting() : 0;
}
bool isStructureContainingArrays() const;
bool isStructureContainingArrays() const {
return structure ? structure->containsArrays() : false;
}
private:
void buildMangledName(TString&);
size_t getStructSize() const;
void computeDeepestStructNesting();
TString buildMangledName() const;
TBasicType type : 6;
TPrecision precision;
......@@ -165,13 +206,9 @@ private:
unsigned int array : 1;
int arraySize;
TTypeList* structure; // 0 unless this is a struct
mutable size_t structureSize;
int deepestStructNesting;
TStructure* structure; // 0 unless this is a struct
TString *fieldName; // for structure field names
TString *mangled;
TString *typeName; // for structure field type name
mutable TString mangled;
};
//
......
......@@ -131,12 +131,13 @@ void getUserDefinedVariableInfo(const TType& type,
{
ASSERT(type.getBasicType() == EbtStruct);
const TTypeList* structure = type.getStruct();
for (size_t i = 0; i < structure->size(); ++i) {
const TType* fieldType = (*structure)[i];
getVariableInfo(*fieldType,
name + "." + fieldType->getFieldName(),
mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction),
const TFieldList& fields = type.getStruct()->fields();
for (size_t i = 0; i < fields.size(); ++i) {
const TType& fieldType = *(fields[i]->type());
const TString& fieldName = fields[i]->name();
getVariableInfo(fieldType,
name + "." + fieldName,
mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
infoList,
hashFunction);
}
......
......@@ -77,8 +77,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TQualifier qualifier;
TFunction* function;
TParameter param;
TType* field;
TTypeList* structure;
TField* field;
TFieldList* fieldList;
};
} interm;
}
......@@ -166,7 +166,7 @@ static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason)
%type <interm.type> type_specifier_no_prec type_specifier_nonarray
%type <interm.type> struct_specifier
%type <interm.field> struct_declarator
%type <interm> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.function> function_header function_declarator function_identifier
%type <interm.function> function_header_with_parameters function_call_header
%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
......@@ -317,7 +317,7 @@ postfix_expression
$$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), @2);
} else if ($1->isArray()) {
if ($1->getType().getStruct())
$$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
$$->setType(TType($1->getType().getStruct()));
else
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
......@@ -391,44 +391,38 @@ postfix_expression
}
} else if ($1->getBasicType() == EbtStruct) {
bool fieldFound = false;
const TTypeList* fields = $1->getType().getStruct();
if (fields == 0) {
context->error(@2, "structure has no fields", "Internal Error");
context->recover();
$$ = $1;
} else {
unsigned int i;
for (i = 0; i < fields->size(); ++i) {
if ((*fields)[i]->getFieldName() == *$3.string) {
fieldFound = true;
break;
}
const TFieldList& fields = $1->getType().getStruct()->fields();
unsigned int i;
for (i = 0; i < fields.size(); ++i) {
if (fields[i]->name() == *$3.string) {
fieldFound = true;
break;
}
if (fieldFound) {
if ($1->getType().getQualifier() == EvqConst) {
$$ = context->addConstStruct(*$3.string, $1, @2);
if ($$ == 0) {
context->recover();
$$ = $1;
}
else {
$$->setType(*(*fields)[i]);
// change the qualifier of the return type, not of the structure field
// as the structure definition is shared between various structures.
$$->getTypePointer()->setQualifier(EvqConst);
}
} else {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(i);
TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i], @3);
$$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
$$->setType(*(*fields)[i]);
}
if (fieldFound) {
if ($1->getType().getQualifier() == EvqConst) {
$$ = context->addConstStruct(*$3.string, $1, @2);
if ($$ == 0) {
context->recover();
$$ = $1;
}
else {
$$->setType(*fields[i]->type());
// change the qualifier of the return type, not of the structure field
// as the structure definition is shared between various structures.
$$->getTypePointer()->setQualifier(EvqConst);
}
} else {
context->error(@2, " no such field in structure", $3.string->c_str());
context->recover();
$$ = $1;
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(i);
TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3);
$$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
$$->setType(*fields[i]->type());
}
} else {
context->error(@2, " no such field in structure", $3.string->c_str());
context->recover();
$$ = $1;
}
} else {
context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
......@@ -1625,7 +1619,7 @@ struct_specifier
if (context->reservedErrorCheck(@2, *$2.string))
context->recover();
TType* structure = new TType($5.structure, *$2.string);
TType* structure = new TType(new TStructure($2.string, $5));
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
if (! context->symbolTable.insert(*userTypeDef)) {
context->error(@2, "redefinition", $2.string->c_str(), "struct");
......@@ -1636,7 +1630,7 @@ struct_specifier
context->exitStructDeclaration();
}
| STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
TType* structure = new TType($4.structure, TString(""));
TType* structure = new TType(new TStructure(NewPoolTString(""), $4));
$$.setBasic(EbtStruct, EvqTemporary, @1);
$$.userDef = structure;
context->exitStructDeclaration();
......@@ -1649,15 +1643,15 @@ struct_declaration_list
}
| struct_declaration_list struct_declaration {
$$ = $1;
for (size_t i = 0; i < $2.structure->size(); ++i) {
TType* field = (*$2.structure)[i];
for (size_t j = 0; j < $$.structure->size(); ++j) {
if ((*$$.structure)[j]->getFieldName() == field->getFieldName()) {
context->error(@2, "duplicate field name in structure:", "struct", field->getFieldName().c_str());
for (size_t i = 0; i < $2->size(); ++i) {
TField* field = (*$2)[i];
for (size_t j = 0; j < $$->size(); ++j) {
if ((*$$)[j]->name() == field->name()) {
context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
context->recover();
}
}
$$.structure->push_back(field);
$$->push_back(field);
}
}
;
......@@ -1666,14 +1660,14 @@ struct_declaration
: type_specifier struct_declarator_list SEMICOLON {
$$ = $2;
if (context->voidErrorCheck(@1, (*$2.structure)[0]->getFieldName(), $1)) {
if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) {
context->recover();
}
for (unsigned int i = 0; i < $$.structure->size(); ++i) {
for (unsigned int i = 0; i < $$->size(); ++i) {
//
// Careful not to replace already known aspects of type, like array-ness
//
TType* type = (*$$.structure)[i];
TType* type = (*$$)[i]->type();
type->setBasicType($1.type);
type->setNominalSize($1.size);
type->setMatrix($1.matrix);
......@@ -1686,25 +1680,22 @@ struct_declaration
}
if ($1.array)
type->setArraySize($1.arraySize);
if ($1.userDef) {
if ($1.userDef)
type->setStruct($1.userDef->getStruct());
type->setTypeName($1.userDef->getTypeName());
}
if (context->structNestingErrorCheck(@1, *type)) {
if (context->structNestingErrorCheck(@1, *(*$$)[i]))
context->recover();
}
}
}
;
struct_declarator_list
: struct_declarator {
$$.structure = NewPoolTTypeList();
$$.structure->push_back($1);
$$ = NewPoolTFieldList();
$$->push_back($1);
}
| struct_declarator_list COMMA struct_declarator {
$$.structure->push_back($3);
$$->push_back($3);
}
;
......@@ -1713,20 +1704,20 @@ struct_declarator
if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
$$ = new TType(EbtVoid, EbpUndefined);
$$->setFieldName(*$1.string);
TType* type = new TType(EbtVoid, EbpUndefined);
$$ = new TField(type, $1.string);
}
| identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
$$ = new TType(EbtVoid, EbpUndefined);
$$->setFieldName(*$1.string);
int size;
if (context->arraySizeErrorCheck(@2, $3, size))
TType* type = new TType(EbtVoid, EbpUndefined);
int size = 0;
if (context->arraySizeErrorCheck(@3, $3, size))
context->recover();
$$->setArraySize(size);
type->setArraySize(size);
$$ = new TField(type, $1.string);
}
;
......
......@@ -178,8 +178,8 @@ typedef union YYSTYPE
TQualifier qualifier;
TFunction* function;
TParameter param;
TType* field;
TTypeList* structure;
TField* field;
TFieldList* fieldList;
};
} interm;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment