Add interface blocks as a basic type and handle uniform blocks that have an instance name. Includes handling qualifiers on structure members.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21093 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
e9942d26f5
commit
f6648dc12c
@ -1,30 +1,30 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
|
|
||||||
layout(location = 7) in vec4 c;
|
layout(location = 7) in vec3 c;
|
||||||
layout(LocatioN = 3) in vec4 p;
|
layout(LocatioN = 3) in vec4 p;
|
||||||
out vec4 pos;
|
out vec4 pos;
|
||||||
out vec4 color;
|
out vec3 color;
|
||||||
|
|
||||||
layout(shared, column_major, row_major) uniform mat4 m4; // default is now shared and row_major
|
layout(shared, column_major, row_major) uniform mat4 m4; // default is now shared and row_major
|
||||||
|
|
||||||
//layout(std140) uniform Transform { // layout of this block is std140
|
layout(std140) uniform Transform { // layout of this block is std140
|
||||||
// mat4 M1; // row_major
|
mat4 M1; // row_major
|
||||||
// layout(column_major) mat4 M2; // column major
|
layout(column_major) mat4 M2; // column major
|
||||||
// mat3 N1; // row_major
|
mat3 N1; // row_major
|
||||||
//};
|
} tblock;
|
||||||
//
|
|
||||||
//uniform T2 { // layout of this block is shared
|
//uniform T2 { // layout of this block is shared
|
||||||
//...
|
//...
|
||||||
//};
|
//};
|
||||||
//
|
//
|
||||||
//layout(column_major) uniform T3 { // shared and column_major
|
layout(column_major) uniform T3 { // shared and column_major
|
||||||
// mat4 M3; // column_major
|
mat4 M3; // column_major
|
||||||
// layout(row_major) mat4 m4; // row major
|
layout(row_major) mat4 m4; // row major
|
||||||
// mat3 N2; // column_major
|
mat3 N2; // column_major
|
||||||
//};
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
pos = p * m4;
|
pos = p * (m4 + tblock.M1 + tblock.M2);
|
||||||
color = c;
|
color = c * tblock.N1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ layout(row_major, column_major)
|
|||||||
|
|
||||||
layout(shared, row_major) uniform; // default is now shared and row_major
|
layout(shared, row_major) uniform; // default is now shared and row_major
|
||||||
|
|
||||||
layout(std140) uniform Transform { // layout of this block is std140
|
layout(std140) uniform Transform2 { // layout of this block is std140
|
||||||
mat4 M1; // row_major
|
mat4 M1; // row_major
|
||||||
layout(column_major) mat4 M2; // column major
|
layout(column_major) mat4 M2; // column major
|
||||||
mat3 N1; // row_major
|
mat3 N1; // row_major
|
||||||
@ -124,7 +124,7 @@ coherent buffer Block {
|
|||||||
vec4 member2;
|
vec4 member2;
|
||||||
};
|
};
|
||||||
|
|
||||||
buffer Block {
|
buffer Block2 {
|
||||||
coherent readonly vec4 member1;
|
coherent readonly vec4 member1;
|
||||||
coherent vec4 member2;
|
coherent vec4 member2;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -49,6 +49,7 @@ enum TBasicType {
|
|||||||
EbtBool,
|
EbtBool,
|
||||||
EbtSampler,
|
EbtSampler,
|
||||||
EbtStruct,
|
EbtStruct,
|
||||||
|
EbtBlock,
|
||||||
EbtNumTypes
|
EbtNumTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -351,7 +351,7 @@ typedef std::map<TTypeList*, TTypeList*>::const_iterator TStructureMapIterator;
|
|||||||
class TType {
|
class TType {
|
||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||||
explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
|
TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
|
||||||
type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
|
type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
|
||||||
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
|
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
|
||||||
fieldName(0), mangled(0), typeName(0)
|
fieldName(0), mangled(0), typeName(0)
|
||||||
@ -382,15 +382,20 @@ public:
|
|||||||
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
explicit TType(TTypeList* userDef, const TString& n) :
|
TType(TTypeList* userDef, const TString& n, TStorageQualifier blockQualifier = EvqGlobal) :
|
||||||
type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), arraySizes(0),
|
type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), arraySizes(0),
|
||||||
structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0)
|
structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0)
|
||||||
{
|
{
|
||||||
sampler.clear();
|
sampler.clear();
|
||||||
qualifier.clear();
|
qualifier.clear();
|
||||||
|
// is it an interface block?
|
||||||
|
if (blockQualifier != EvqGlobal) {
|
||||||
|
qualifier.storage = blockQualifier;
|
||||||
|
type = EbtBlock;
|
||||||
|
}
|
||||||
typeName = NewPoolTString(n.c_str());
|
typeName = NewPoolTString(n.c_str());
|
||||||
}
|
}
|
||||||
explicit TType() {}
|
TType() {}
|
||||||
virtual ~TType() {}
|
virtual ~TType() {}
|
||||||
|
|
||||||
TType(const TType& type) { *this = type; }
|
TType(const TType& type) { *this = type; }
|
||||||
@ -513,6 +518,9 @@ public:
|
|||||||
void setArrayInformationType(TType* t) { arrayInformationType = t; }
|
void setArrayInformationType(TType* t) { arrayInformationType = t; }
|
||||||
TType* getArrayInformationType() { return arrayInformationType; }
|
TType* getArrayInformationType() { return arrayInformationType; }
|
||||||
virtual bool isVector() const { return vectorSize > 1; }
|
virtual bool isVector() const { return vectorSize > 1; }
|
||||||
|
const char* getBasicString() const {
|
||||||
|
return TType::getBasicString(type);
|
||||||
|
}
|
||||||
static const char* getBasicString(TBasicType t) {
|
static const char* getBasicString(TBasicType t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case EbtVoid: return "void";
|
case EbtVoid: return "void";
|
||||||
@ -523,6 +531,7 @@ public:
|
|||||||
case EbtBool: return "bool";
|
case EbtBool: return "bool";
|
||||||
case EbtSampler: return "sampler/image";
|
case EbtSampler: return "sampler/image";
|
||||||
case EbtStruct: return "structure";
|
case EbtStruct: return "structure";
|
||||||
|
case EbtBlock: return "block";
|
||||||
default: return "unknown type";
|
default: return "unknown type";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,10 +607,9 @@ public:
|
|||||||
if (type == EbtSampler)
|
if (type == EbtSampler)
|
||||||
return sampler.getString();
|
return sampler.getString();
|
||||||
else
|
else
|
||||||
return getBasicString(type);
|
return getBasicString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getBasicString() const { return TType::getBasicString(type); }
|
|
||||||
const char* getStorageQualifierString() const { return ::getStorageQualifierString(qualifier.storage); }
|
const char* getStorageQualifierString() const { return ::getStorageQualifierString(qualifier.storage); }
|
||||||
const char* getPrecisionQualifierString() const { return ::getPrecisionQualifierString(qualifier.precision); }
|
const char* getPrecisionQualifierString() const { return ::getPrecisionQualifierString(qualifier.precision); }
|
||||||
TTypeList* getStruct() { return structure; }
|
TTypeList* getStruct() { return structure; }
|
||||||
@ -610,7 +618,7 @@ public:
|
|||||||
{
|
{
|
||||||
int totalSize;
|
int totalSize;
|
||||||
|
|
||||||
if (getBasicType() == EbtStruct)
|
if (getBasicType() == EbtStruct || getBasicType() == EbtBlock)
|
||||||
totalSize = getStructSize();
|
totalSize = getStructSize();
|
||||||
else if (matrixCols)
|
else if (matrixCols)
|
||||||
totalSize = matrixCols * matrixRows;
|
totalSize = matrixCols * matrixRows;
|
||||||
|
|||||||
@ -71,6 +71,9 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
|
|||||||
//
|
//
|
||||||
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
|
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
|
||||||
{
|
{
|
||||||
|
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case EOpLessThan:
|
case EOpLessThan:
|
||||||
case EOpGreaterThan:
|
case EOpGreaterThan:
|
||||||
@ -199,6 +202,9 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
|||||||
{
|
{
|
||||||
TIntermTyped* child = childNode->getAsTyped();
|
TIntermTyped* child = childNode->getAsTyped();
|
||||||
|
|
||||||
|
if (child->getType().getBasicType() == EbtBlock)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
|
infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -717,43 +717,43 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Merge characteristics of the 'right' qualifier into the 'left'.
|
// Merge characteristics of the 'src' qualifier into the 'dst'.
|
||||||
// If there is duplication, issue error messages.
|
// If there is duplication, issue error messages, unless 'force'
|
||||||
|
// is specified, which means to just override default settings.
|
||||||
//
|
//
|
||||||
// Return true if there was an error.
|
// Return true if there was an error.
|
||||||
//
|
//
|
||||||
bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right)
|
bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force)
|
||||||
{
|
{
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
|
|
||||||
// Storage qualification
|
// Storage qualification
|
||||||
if (left.qualifier.storage == EvqTemporary)
|
if (dst.qualifier.storage == EvqTemporary || dst.qualifier.storage == EvqGlobal)
|
||||||
left.qualifier.storage = right.qualifier.storage;
|
dst.qualifier.storage = src.qualifier.storage;
|
||||||
else if (left.qualifier.storage == EvqIn && right.qualifier.storage == EvqOut ||
|
else if (dst.qualifier.storage == EvqIn && src.qualifier.storage == EvqOut ||
|
||||||
left.qualifier.storage == EvqOut && right.qualifier.storage == EvqIn)
|
dst.qualifier.storage == EvqOut && src.qualifier.storage == EvqIn)
|
||||||
left.qualifier.storage = EvqInOut;
|
dst.qualifier.storage = EvqInOut;
|
||||||
else if (left.qualifier.storage == EvqIn && right.qualifier.storage == EvqConst ||
|
else if (dst.qualifier.storage == EvqIn && src.qualifier.storage == EvqConst ||
|
||||||
left.qualifier.storage == EvqConst && right.qualifier.storage == EvqIn)
|
dst.qualifier.storage == EvqConst && src.qualifier.storage == EvqIn)
|
||||||
left.qualifier.storage = EvqConstReadOnly;
|
dst.qualifier.storage = EvqConstReadOnly;
|
||||||
else if ( left.qualifier.storage != EvqTemporary &&
|
else if (src.qualifier.storage != EvqTemporary) {
|
||||||
right.qualifier.storage != EvqTemporary) {
|
error(line, "too many storage qualifiers", getStorageQualifierString(src.qualifier.storage), "");
|
||||||
error(line, "too many storage qualifiers", getStorageQualifierString(right.qualifier.storage), "");
|
|
||||||
bad = true;
|
bad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precision qualifiers
|
// Precision qualifiers
|
||||||
if (left.qualifier.precision == EpqNone)
|
if (! force && src.qualifier.precision != EpqNone && dst.qualifier.precision != EpqNone) {
|
||||||
left.qualifier.precision = right.qualifier.precision;
|
error(line, "only one precision qualifier allowed", getPrecisionQualifierString(src.qualifier.precision), "");
|
||||||
else if (right.qualifier.precision) {
|
|
||||||
error(line, "only one precision qualifier allowed", getPrecisionQualifierString(right.qualifier.precision), "");
|
|
||||||
bad = true;
|
bad = true;
|
||||||
}
|
}
|
||||||
|
if (dst.qualifier.precision == EpqNone || force && src.qualifier.precision != EpqNone)
|
||||||
|
dst.qualifier.precision = src.qualifier.precision;
|
||||||
|
|
||||||
// Layout qualifiers
|
// Layout qualifiers
|
||||||
mergeLayoutQualifiers(line, left, right);
|
mergeLayoutQualifiers(line, dst, src);
|
||||||
|
|
||||||
// other qualifiers
|
// other qualifiers
|
||||||
#define MERGE_SINGLETON(field) bad |= left.qualifier.field && right.qualifier.field; left.qualifier.field |= right.qualifier.field;
|
#define MERGE_SINGLETON(field) bad |= dst.qualifier.field && src.qualifier.field; dst.qualifier.field |= src.qualifier.field;
|
||||||
MERGE_SINGLETON(invariant);
|
MERGE_SINGLETON(invariant);
|
||||||
MERGE_SINGLETON(centroid);
|
MERGE_SINGLETON(centroid);
|
||||||
MERGE_SINGLETON(smooth);
|
MERGE_SINGLETON(smooth);
|
||||||
@ -1461,6 +1461,72 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
|
|||||||
return converted;
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do everything needed to add an interface block.
|
||||||
|
//
|
||||||
|
void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes)
|
||||||
|
{
|
||||||
|
// First, error checks
|
||||||
|
|
||||||
|
if (reservedErrorCheck(line, blockName)) {
|
||||||
|
recover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (instanceName && reservedErrorCheck(line, *instanceName)) {
|
||||||
|
recover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qualifier.type != EbtVoid) {
|
||||||
|
error(line, "interface blocks cannot be declared with a type", blockName.c_str(), "");
|
||||||
|
recover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qualifier.qualifier.storage == EvqUniform) {
|
||||||
|
requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block");
|
||||||
|
profileRequires(line, EEsProfile, 300, 0, "uniform block");
|
||||||
|
} else {
|
||||||
|
error(line, "only uniform interface blocks are supported", blockName.c_str(), "");
|
||||||
|
recover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build and add the interface block as a new type named blockName
|
||||||
|
|
||||||
|
TType* blockType = new TType(&typeList, blockName, qualifier.qualifier.storage);
|
||||||
|
TVariable* userTypeDef = new TVariable(&blockName, *blockType, true);
|
||||||
|
if (! symbolTable.insert(*userTypeDef)) {
|
||||||
|
error(line, "redefinition", blockName.c_str(), "block name");
|
||||||
|
recover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: semantics: check for qualifiers that don't belong within a block
|
||||||
|
for (unsigned int member = 0; member < typeList.size(); ++member) {
|
||||||
|
//printf("%s: %s\n", typeList[member].type->getFieldName().c_str(), typeList[member].type->getCompleteString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the variable, as anonymous or named instanceName
|
||||||
|
|
||||||
|
// make an anonymous variable if no name was provided
|
||||||
|
if (! instanceName)
|
||||||
|
instanceName = new TString("");
|
||||||
|
|
||||||
|
TVariable* variable = new TVariable(instanceName, *blockType);
|
||||||
|
|
||||||
|
if (! symbolTable.insert(*variable)) {
|
||||||
|
error(line, "redefinition", variable->getName().c_str(), "");
|
||||||
|
delete variable;
|
||||||
|
recover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
|
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
|
||||||
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
|
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
|
||||||
|
|||||||
@ -122,7 +122,7 @@ struct TParseContext {
|
|||||||
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
|
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
|
||||||
bool globalQualifierFixAndErrorCheck(int line, TQualifier&, const TPublicType&);
|
bool globalQualifierFixAndErrorCheck(int line, TQualifier&, const TPublicType&);
|
||||||
bool structQualifierErrorCheck(int line, const TPublicType& pType);
|
bool structQualifierErrorCheck(int line, const TPublicType& pType);
|
||||||
bool mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right);
|
bool mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force);
|
||||||
void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);
|
void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);
|
||||||
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
|
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
|
||||||
bool containsSampler(const TType& type);
|
bool containsSampler(const TType& type);
|
||||||
@ -140,10 +140,12 @@ struct TParseContext {
|
|||||||
TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
|
TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
|
||||||
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
|
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
|
||||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
|
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
|
||||||
|
void addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
|
||||||
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
|
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
|
||||||
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
|
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
|
||||||
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
||||||
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
|
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
|
||||||
|
|
||||||
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
|
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
|
||||||
void requireProfile(int line, EProfileMask profileMask, const char *featureDesc);
|
void requireProfile(int line, EProfileMask profileMask, const char *featureDesc);
|
||||||
void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc);
|
void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc);
|
||||||
|
|||||||
@ -406,7 +406,7 @@ postfix_expression
|
|||||||
} else if ($1->isMatrix()) {
|
} else if ($1->isMatrix()) {
|
||||||
parseContext.error($2.line, "field selection not allowed on matrix", ".", "");
|
parseContext.error($2.line, "field selection not allowed on matrix", ".", "");
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
} else if ($1->getBasicType() == EbtStruct) {
|
} else if ($1->getBasicType() == EbtStruct || $1->getBasicType() == EbtBlock) {
|
||||||
bool fieldFound = false;
|
bool fieldFound = false;
|
||||||
TTypeList* fields = $1->getType().getStruct();
|
TTypeList* fields = $1->getType().getStruct();
|
||||||
if (fields == 0) {
|
if (fields == 0) {
|
||||||
@ -1184,15 +1184,15 @@ declaration
|
|||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
| type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON {
|
| type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON {
|
||||||
// block
|
parseContext.addBlock($2.line, $1, *$2.string, *$4);
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
| type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
|
| type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
|
||||||
// block
|
parseContext.addBlock($2.line, $1, *$2.string, *$4, $6.string);
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
| type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON {
|
| type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON {
|
||||||
// block
|
parseContext.addBlock($2.line, $1, *$2.string, *$4, $6.string, $7.arraySizes);
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
| type_qualifier SEMICOLON {
|
| type_qualifier SEMICOLON {
|
||||||
@ -1665,7 +1665,7 @@ type_qualifier
|
|||||||
if ($$.type == EbtVoid)
|
if ($$.type == EbtVoid)
|
||||||
$$.type = $2.type;
|
$$.type = $2.type;
|
||||||
|
|
||||||
if (parseContext.mergeQualifiersErrorCheck($$.line, $$, $2))
|
if (parseContext.mergeQualifiersErrorCheck($$.line, $$, $2, false))
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -2530,6 +2530,7 @@ precision_qualifier
|
|||||||
|
|
||||||
struct_specifier
|
struct_specifier
|
||||||
: STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
|
: STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
|
||||||
|
// TODO: semantics: check for qualifiers that don't belong in a struct
|
||||||
TType* structure = new TType($4, *$2.string);
|
TType* structure = new TType($4, *$2.string);
|
||||||
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
|
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
|
||||||
if (! parseContext.symbolTable.insert(*userTypeDef)) {
|
if (! parseContext.symbolTable.insert(*userTypeDef)) {
|
||||||
@ -2557,7 +2558,7 @@ struct_declaration_list
|
|||||||
for (unsigned int i = 0; i < $2->size(); ++i) {
|
for (unsigned int i = 0; i < $2->size(); ++i) {
|
||||||
for (unsigned int j = 0; j < $$->size(); ++j) {
|
for (unsigned int j = 0; j < $$->size(); ++j) {
|
||||||
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
|
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
|
||||||
parseContext.error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
|
parseContext.error((*$2)[i].line, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2598,15 +2599,16 @@ struct_declaration
|
|||||||
|
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
|
|
||||||
if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2)) {
|
if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2))
|
||||||
|
parseContext.recover();
|
||||||
|
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
}
|
|
||||||
for (unsigned int i = 0; i < $$->size(); ++i) {
|
for (unsigned int i = 0; i < $$->size(); ++i) {
|
||||||
//
|
//
|
||||||
// Careful not to replace already know aspects of type, like array-ness
|
// Careful not to replace already know aspects of type, like array-ness
|
||||||
//
|
//
|
||||||
(*$$)[i].type->setElementType($2.type, $2.vectorSize, $2.matrixCols, $2.matrixRows, $2.userDef);
|
(*$$)[i].type->setElementType($2.type, $2.vectorSize, $2.matrixCols, $2.matrixRows, $2.userDef);
|
||||||
|
(*$$)[i].type->getQualifier() = $2.qualifier;
|
||||||
if ($2.arraySizes)
|
if ($2.arraySizes)
|
||||||
(*$$)[i].type->setArraySizes($2.arraySizes);
|
(*$$)[i].type->setArraySizes($2.arraySizes);
|
||||||
if ($2.userDef)
|
if ($2.userDef)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user