From ba042100975bd7b56f4091091ec9ee36256e7701 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 10 Apr 2013 20:15:16 +0000 Subject: [PATCH] Add anonymous members as a new symbol table type, so the infrastructure can handle blocks with no names. Also, add more safety to the types involved regarding copy constructors, operator=, etc. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21106 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/300layout.vert | 17 ++-- Test/specExamples.vert | 10 +-- glslang/Include/Types.h | 8 +- glslang/MachineIndependent/Constant.cpp | 4 +- glslang/MachineIndependent/ParseHelper.cpp | 19 ++--- glslang/MachineIndependent/QualifierAlive.cpp | 2 +- glslang/MachineIndependent/SymbolTable.cpp | 16 +++- glslang/MachineIndependent/SymbolTable.h | 104 +++++++++++++++++++------ glslang/MachineIndependent/glslang.y | 53 ++++++++----- glslang/MachineIndependent/localintermediate.h | 2 +- glslang/MachineIndependent/parseConst.cpp | 6 +- 11 files changed, 169 insertions(+), 72 deletions(-) diff --git a/Test/300layout.vert b/Test/300layout.vert index 89fb17b..60ef585 100644 --- a/Test/300layout.vert +++ b/Test/300layout.vert @@ -5,7 +5,8 @@ layout(LocatioN = 3) in vec4 p; out vec4 pos; 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 badm4; // ERROR +layout(shared, column_major, row_major) uniform; // default is now shared and row_major layout(std140) uniform Transform { // layout of this block is std140 mat4 M1; // row_major @@ -13,18 +14,20 @@ layout(std140) uniform Transform { // layout of this block is std140 mat3 N1; // row_major } tblock; -//uniform T2 { // layout of this block is shared -//... -//}; -// +uniform T2 { // layout of this block is shared + bool b; + mat4 t2m; +}; + layout(column_major) uniform T3 { // shared and column_major mat4 M3; // column_major - layout(row_major) mat4 m4; // row major + layout(row_major) mat4 M4; // row major mat3 N2; // column_major + int b; // ERROR, redefinition (needs to be last member of block for testing, following members are skipped) }; void main() { - pos = p * (m4 + tblock.M1 + tblock.M2); + pos = p * (tblock.M1 + tblock.M2 + M4 + M3 + t2m); color = c * tblock.N1; } diff --git a/Test/specExamples.vert b/Test/specExamples.vert index bc406a9..c4b283c 100644 --- a/Test/specExamples.vert +++ b/Test/specExamples.vert @@ -68,16 +68,16 @@ layout(std140) uniform Transform2 { // layout of this block is std140 }; layout(column_major) uniform T3 { // shared and column_major - mat4 M3; // column_major - layout(row_major) mat4 m4; // row major - mat3 N2; // column_major + mat4 M13; // column_major + layout(row_major) mat4 m14; // row major + mat3 N12; // column_major }; // in one compilation unit... -layout(binding=3) uniform sampler2D s; // s bound to unit 3 +layout(binding=3) uniform sampler2D s17; // s bound to unit 3 // in another compilation unit... -uniform sampler2D s; // okay, s still bound at 3 +uniform sampler2D s17; // okay, s still bound at 3 // in another compilation unit... //layout(binding=4) uniform sampler2D s; // ERROR: contradictory bindings diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 95720ab..b0f60c1 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -398,7 +398,11 @@ public: TType() {} virtual ~TType() {} - TType(const TType& type) { *this = type; } + // "dumb" copy, using built-in operator=(), not for use across pool pops. + // It will also cause multiple copies of TType to point to the same information. + // This only works if that information (like a structure's list of types) does not + // change. + explicit TType(const TType& type) { *this = type; } void copyType(const TType& copyOf, const TStructureMap& remapper) { @@ -680,7 +684,7 @@ protected: TArraySizes arraySizes; TTypeList* structure; // 0 unless this is a struct - mutable int structureSize; + mutable int structureSize; // a cache, updated on first access int maxArraySize; TType* arrayInformationType; TString *fieldName; // for structure field names diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index 27130d8..e8c42a7 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -48,7 +48,7 @@ bool CompareStruct(const TType& leftNodeType, constUnion* rightUnionArray, const bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray) { if (leftNodeType.isArray()) { - TType typeWithoutArrayness = leftNodeType; + TType typeWithoutArrayness(leftNodeType); typeWithoutArrayness.dereference(); int arraySize = leftNodeType.getArraySize(); @@ -111,7 +111,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod // For most cases, the return type matches the argument type, so set that // up and just code to exceptions below. - TType returnType = getType(); + TType returnType(getType()); // // A pair of nodes is to be folded together diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 2b3b289..3f8df15 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -1183,7 +1183,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { - TType type = TType(pType); + TType type(pType); if (variable == 0) { if (reservedErrorCheck(line, identifier)) @@ -1286,7 +1286,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType& type if (op == EOpConstructStruct) memberTypes = type.getStruct()->begin(); - TType elementType = type; + TType elementType(type); if (type.isArray()) elementType.dereference(); @@ -1496,8 +1496,8 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl // 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); + TType blockType(&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(); @@ -1516,11 +1516,12 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl if (! instanceName) instanceName = new TString(""); - TVariable* variable = new TVariable(instanceName, *blockType); - + TVariable* variable = new TVariable(instanceName, blockType); if (! symbolTable.insert(*variable)) { - error(line, "redefinition", variable->getName().c_str(), ""); - delete variable; + if (*instanceName == "") + error(line, "nameless block contains a member that already has a name at global scope", blockName.c_str(), ""); + else + error(line, "block instance name redefinition", variable->getName().c_str(), ""); recover(); return; @@ -1616,7 +1617,7 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); int arraySize = node->getType().getArraySize(); - TType arrayElementType = node->getType(); + TType arrayElementType(node->getType()); arrayElementType.dereference(); if (index >= node->getType().getArraySize() || index < 0) { diff --git a/glslang/MachineIndependent/QualifierAlive.cpp b/glslang/MachineIndependent/QualifierAlive.cpp index d892c79..ea56fa3 100644 --- a/glslang/MachineIndependent/QualifierAlive.cpp +++ b/glslang/MachineIndependent/QualifierAlive.cpp @@ -58,7 +58,7 @@ protected: // is guaranteed written. Not always possible to determine if // it is written conditionally. // -// ?? It does not do this well yet, this is just a place holder +// It does not do this well yet, this is just a place holder // that simply determines if it was reference at all, anywhere. // bool QualifierWritten(TIntermNode* node, TStorageQualifier qualifier) diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 089b372..64a13c5 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -141,11 +141,16 @@ void TVariable::dump(TInfoSink& infoSink) const infoSink.debug << "\n"; } -void TFunction::dump(TInfoSink &infoSink) const +void TFunction::dump(TInfoSink& infoSink) const { infoSink.debug << getName().c_str() << ": " << returnType.getCompleteTypeString() << " " << getMangledName().c_str() << "\n"; } +void TAnonMember::dump(TInfoSink& TInfoSink) const +{ + TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str() << "\n"; +} + void TSymbolTableLevel::dump(TInfoSink &infoSink) const { tLevel::const_iterator it; @@ -250,9 +255,18 @@ TFunction* TFunction::clone(TStructureMap& remapper) return function; } +TAnonMember* TAnonMember::clone(TStructureMap& remapper) +{ + // need to implement this once built-in symbols include interface blocks + assert(0); + + return 0; +} + TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper) { TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); + symTableLevel->anonId = anonId; tLevel::iterator iter; for (iter = level.begin(); iter != level.end(); ++iter) { symTableLevel->insert(*iter->second->clone(remapper)); diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index 836c83a..e7a76cd 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -42,6 +42,11 @@ // effort of creating and loading with the large numbers of built-in // symbols. // +// --> This requires a copy mechanism, so initial pools used to create +// the shared information can be popped. So, care is taken with +// copying pointers to point to new copies. Done through "clone" +// methods. +// // * Name mangling will be used to give each function a unique name // so that symbol table lookups are never ambiguous. This allows // a simpler symbol table structure. @@ -67,24 +72,30 @@ // class TVariable; class TFunction; +class TAnonMember; class TSymbol { public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - TSymbol(const TString *n) : name(n) { } - virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + explicit TSymbol(const TString *n) : name(n) { } + virtual TSymbol* clone(TStructureMap& remapper) = 0; + virtual ~TSymbol() { } + const TString& getName() const { return *name; } + void changeName(const char* buf) { name = new TString(buf); } virtual const TString& getMangledName() const { return getName(); } virtual TFunction* getAsFunction() { return 0; } virtual TVariable* getAsVariable() { return 0; } + virtual TAnonMember* getAsAnonMember() { return 0; } void setUniqueId(int id) { uniqueId = id; } int getUniqueId() const { return uniqueId; } - virtual void dump(TInfoSink &infoSink) const = 0; - TSymbol(const TSymbol&); - virtual TSymbol* clone(TStructureMap& remapper) = 0; + virtual void dump(TInfoSink &infoSink) const = 0; protected: + explicit TSymbol(const TSymbol&); + TSymbol& operator=(const TSymbol&); + const TString *name; - unsigned int uniqueId; // For real comparing during code generation + unsigned int uniqueId; // For cross-scope comparing during code generation }; // @@ -99,8 +110,10 @@ protected: // class TVariable : public TSymbol { public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } + virtual TVariable* clone(TStructureMap& remapper); virtual ~TVariable() { } + virtual TVariable* getAsVariable() { return this; } TType& getType() { return type; } const TType& getType() const { return type; } @@ -125,10 +138,12 @@ public: delete unionArray; unionArray = constArray; } - TVariable(const TVariable&, TStructureMap& remapper); // copy constructor - virtual TVariable* clone(TStructureMap& remapper); protected: + explicit TVariable(TVariable&); + TVariable(const TVariable&, TStructureMap& remapper); + TVariable& operator=(TVariable&); + TType type; bool userType; // we are assuming that Pool Allocator will free the memory allocated to unionArray @@ -159,7 +174,7 @@ struct TParameter { // class TFunction : public TSymbol { public: - TFunction(TOperator o) : + explicit TFunction(TOperator o) : TSymbol(0), returnType(TType(EbtVoid)), op(o), @@ -169,9 +184,10 @@ public: returnType(retType), mangledName(*name + '('), op(tOp), - defined(false) { } - TFunction(const TFunction&, const TStructureMap& remapper); + defined(false) { } + virtual TFunction* clone(TStructureMap& remapper); virtual ~TFunction(); + virtual TFunction* getAsFunction() { return this; } void addParameter(TParameter& p) @@ -192,9 +208,12 @@ public: const TParameter& operator [](int i) const { return parameters[i]; } virtual void dump(TInfoSink &infoSink) const; - virtual TFunction* clone(TStructureMap& remapper); protected: + explicit TFunction(TFunction&); + TFunction(const TFunction&, const TStructureMap& remapper); + TFunction& operator=(TFunction&); + typedef TVector TParamList; TParamList parameters; TType returnType; @@ -203,11 +222,29 @@ protected: bool defined; }; +class TAnonMember : public TSymbol { +public: + TAnonMember(const TString* n, unsigned int m, TSymbol& a) : TSymbol(n), anonContainer(a), memberNumber(m) { } + virtual TAnonMember* clone(TStructureMap& remapper); + virtual ~TAnonMember() { } + + TAnonMember* getAsAnonMember() { return this; } + TSymbol& getAnonContainer() const { return anonContainer; } + unsigned int getMemberNumber() const { return memberNumber; } + virtual void dump(TInfoSink &infoSink) const; + +protected: + explicit TAnonMember(TAnonMember&); + TAnonMember& operator=(TAnonMember&); + + TSymbol& anonContainer; + unsigned int memberNumber; +}; class TSymbolTableLevel { public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - TSymbolTableLevel() : defaultPrecision (0) { } + TSymbolTableLevel() : defaultPrecision (0), anonId(0) { } ~TSymbolTableLevel(); bool insert(TSymbol& symbol) @@ -216,15 +253,34 @@ public: // returning true means symbol was added to the table // tInsertResult result; - result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); - - return result.second; + if (symbol.getName() == "") { + // An empty name means an anonymous container, exposing its members to the external scope. + // Give it a name and insert its members in the symbol table, pointing to the container. + char buf[20]; + snprintf(buf, 20, "__anon__%d", anonId++); + symbol.changeName(buf); + + bool isOkay = true; + TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); + for (unsigned int m = 0; m < types.size(); ++m) { + TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, symbol); + result = level.insert(tLevelPair(member->getMangledName(), member)); + if (! result.second) + isOkay = false; + } + + return isOkay; + } else { + result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + + return result.second; + } } TSymbol* find(const TString& name) const { tLevel::const_iterator it = level.find(name); - if (it == level.end()) + if (it == level.end()) return 0; else return (*it).second; @@ -262,12 +318,16 @@ public: TSymbolTableLevel* clone(TStructureMap& remapper); protected: + explicit TSymbolTableLevel(TSymbolTableLevel&); + TSymbolTableLevel& operator=(TSymbolTableLevel&); + typedef std::map, pool_allocator > > tLevel; typedef const tLevel::value_type tLevelPair; typedef std::pair tInsertResult; - tLevel level; + tLevel level; // named mappings TPrecisionQualifier *defaultPrecision; + int anonId; }; class TSymbolTable { @@ -280,13 +340,11 @@ public: // that the symbol table has not been preloaded with built-ins. // } - - TSymbolTable(TSymbolTable& symTable) + explicit TSymbolTable(TSymbolTable& symTable) { table.push_back(symTable.table[0]); uniqueId = symTable.uniqueId; } - ~TSymbolTable() { // level 0 is always built In symbols, so we never pop that out @@ -347,6 +405,8 @@ public: void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } protected: + TSymbolTable& operator=(TSymbolTableLevel&); + int currentLevel() const { return static_cast(table.size()) - 1; } bool atDynamicBuiltInLevel() { return table.size() == 2; } diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index e56125c..954e5bd 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -223,26 +223,41 @@ variable_identifier // if this is a new symbol, it won't find it, which is okay at this // point in the grammar. TSymbol* symbol = $1.symbol; - const TVariable* variable = symbol ? symbol->getAsVariable() : 0; - if (symbol && ! variable) { - parseContext.error($1.line, "variable name expected", $1.string->c_str(), ""); - parseContext.recover(); - } + TAnonMember* anon = symbol ? symbol->getAsAnonMember() : 0; + if (anon) { + // it was a member of an anonymous container, have to insert its dereference + TVariable* variable = anon->getAnonContainer().getAsVariable(); + TIntermTyped* container = parseContext.intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), $1.line); + constUnion* unionArray = new constUnion[1]; + unionArray->setUConst(anon->getMemberNumber()); + TIntermTyped* constNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.line); + + $$ = parseContext.intermediate.addIndex(EOpIndexDirect, container, constNode, $1.line); + $$->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); + } else { + const TVariable* variable = symbol ? symbol->getAsVariable() : 0; + if (symbol && ! variable) { + parseContext.error($1.line, "variable name expected", $1.string->c_str(), ""); + parseContext.recover(); + } - if (! variable) - variable = new TVariable($1.string, TType(EbtVoid)); + if (! variable) + variable = new TVariable($1.string, TType(EbtVoid)); - // don't delete $1.string, it's used by error recovery, and the pool - // pop will reclaim the memory + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory - if (variable->getType().getQualifier().storage == EvqConst ) { - constUnion* constArray = variable->getConstUnionPointer(); - TType t(variable->getType()); - $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line); - } else - $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line); + if (variable->getType().getQualifier().storage == EvqConst ) { + constUnion* constArray = variable->getConstUnionPointer(); + TType t(variable->getType()); + $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line); + } else + $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), $1.line); + } } ; @@ -346,7 +361,7 @@ postfix_expression unionArray->setFConst(0.0f); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line); } else { - TType newType = $1->getType(); + TType newType($1->getType()); newType.dereference(); $$->setType(newType); // TODO: testing: write a set of dereference tests @@ -400,7 +415,7 @@ postfix_expression TString vectorString = *$3.string; TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line); $$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); - $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size())); + $$->setType(TType($1->getBasicType(), EvqTemporary, (int) vectorString.size())); } } } else if ($1->isMatrix()) { diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index aabab27..ab0c0db 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -74,7 +74,7 @@ public: TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc); TIntermConstantUnion* addConstantUnion(constUnion*, const TType&, TSourceLoc); TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; - bool parseConstTree(TSourceLoc, TIntermNode*, constUnion*, TOperator, TType, bool singleConstantParam = false); + bool parseConstTree(TSourceLoc, TIntermNode*, constUnion*, TOperator, const TType&, bool singleConstantParam = false); TIntermNode* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc); TIntermBranch* addBranch(TOperator, TSourceLoc); TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); diff --git a/glslang/MachineIndependent/parseConst.cpp b/glslang/MachineIndependent/parseConst.cpp index c797374..df6d1e7 100644 --- a/glslang/MachineIndependent/parseConst.cpp +++ b/glslang/MachineIndependent/parseConst.cpp @@ -40,13 +40,13 @@ // class TConstTraverser : public TIntermTraverser { public: - TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t) : unionArray(cUnion), type(t), + TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, const TType& t) : unionArray(cUnion), type(t), constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), error(false), isMatrix(false), matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull;} int index ; constUnion *unionArray; TOperator tOp; - TType type; + const TType& type; TOperator constructorType; bool singleConstantParam; TInfoSink& infoSink; @@ -255,7 +255,7 @@ bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it) // Individual functions can be initialized to 0 to skip processing of that // type of node. It's children will still be processed. // -bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam) +bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, const TType& t, bool singleConstantParam) { if (root == 0) return false; -- 2.7.4