Add anonymous members as a new symbol table type, so the infrastructure can handle...
authorJohn Kessenich <cepheus@frii.com>
Wed, 10 Apr 2013 20:15:16 +0000 (20:15 +0000)
committerJohn Kessenich <cepheus@frii.com>
Wed, 10 Apr 2013 20:15:16 +0000 (20:15 +0000)
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
Test/specExamples.vert
glslang/Include/Types.h
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/QualifierAlive.cpp
glslang/MachineIndependent/SymbolTable.cpp
glslang/MachineIndependent/SymbolTable.h
glslang/MachineIndependent/glslang.y
glslang/MachineIndependent/localintermediate.h
glslang/MachineIndependent/parseConst.cpp

index 89fb17b..60ef585 100644 (file)
@@ -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;
 }
index bc406a9..c4b283c 100644 (file)
@@ -68,16 +68,16 @@ layout(std140) uniform Transform2 { // layout of this block is std140
 };\r
 \r
 layout(column_major) uniform T3 {  // shared and column_major\r
-    mat4 M3;                       // column_major\r
-    layout(row_major) mat4 m4;     // row major\r
-    mat3 N2;                       // column_major\r
+    mat4 M13;                      // column_major\r
+    layout(row_major) mat4 m14;    // row major\r
+    mat3 N12;                      // column_major\r
 };\r
 \r
 // in one compilation unit...\r
-layout(binding=3) uniform sampler2D s; // s bound to unit 3\r
+layout(binding=3) uniform sampler2D s17; // s bound to unit 3\r
 \r
 // in another compilation unit...\r
-uniform sampler2D s;                   // okay, s still bound at 3\r
+uniform sampler2D s17;                   // okay, s still bound at 3\r
 \r
 // in another compilation unit...\r
 //layout(binding=4) uniform sampler2D s; // ERROR: contradictory bindings\r
index 95720ab..b0f60c1 100644 (file)
@@ -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
index 27130d8..e8c42a7 100644 (file)
@@ -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
index 2b3b289..3f8df15 100644 (file)
@@ -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) {
index d892c79..ea56fa3 100644 (file)
@@ -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)
index 089b372..64a13c5 100644 (file)
@@ -141,11 +141,16 @@ void TVariable::dump(TInfoSink& infoSink) const
     infoSink.debug << "\n";
 }
 
-void TFunction::dump(TInfoSink &infoSink) const
+void TFunction::dump(TInfoSinkinfoSink) 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));
index 836c83a..e7a76cd 100644 (file)
 //   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.
 //
 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<TParameter> 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<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
     typedef const tLevel::value_type tLevelPair;
     typedef std::pair<tLevel::iterator, bool> 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<int>(table.size()) - 1; }
     bool atDynamicBuiltInLevel() { return table.size() == 2; }
 
index e56125c..954e5bd 100644 (file)
@@ -223,26 +223,41 @@ variable_identifier
         // if this is a new symbol, it won't find it, which is okay at this\r
         // point in the grammar.\r
         TSymbol* symbol = $1.symbol;\r
-        const TVariable* variable = symbol ? symbol->getAsVariable() : 0;\r
-        if (symbol && ! variable) {\r
-            parseContext.error($1.line, "variable name expected", $1.string->c_str(), "");\r
-            parseContext.recover();\r
-        }\r
+        TAnonMember* anon = symbol ? symbol->getAsAnonMember() : 0;\r
+        if (anon) {\r
+            // it was a member of an anonymous container, have to insert its dereference\r
+            TVariable* variable = anon->getAnonContainer().getAsVariable();\r
+            TIntermTyped* container = parseContext.intermediate.addSymbol(variable->getUniqueId(),\r
+                                                                          variable->getName(),\r
+                                                                          variable->getType(), $1.line);\r
+            constUnion* unionArray = new constUnion[1];\r
+            unionArray->setUConst(anon->getMemberNumber());\r
+            TIntermTyped* constNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.line);\r
+\r
+            $$ = parseContext.intermediate.addIndex(EOpIndexDirect, container, constNode, $1.line);\r
+            $$->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);\r
+        } else {\r
+            const TVariable* variable = symbol ? symbol->getAsVariable() : 0;\r
+            if (symbol && ! variable) {\r
+                parseContext.error($1.line, "variable name expected", $1.string->c_str(), "");\r
+                parseContext.recover();\r
+            }\r
 \r
-        if (! variable)\r
-            variable = new TVariable($1.string, TType(EbtVoid));\r
+            if (! variable)\r
+                variable = new TVariable($1.string, TType(EbtVoid));\r
 \r
-        // don't delete $1.string, it's used by error recovery, and the pool\r
-        // pop will reclaim the memory\r
+            // don't delete $1.string, it's used by error recovery, and the pool\r
+            // pop will reclaim the memory\r
 \r
-        if (variable->getType().getQualifier().storage == EvqConst ) {\r
-            constUnion* constArray = variable->getConstUnionPointer();\r
-            TType t(variable->getType());\r
-            $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);\r
-        } else\r
-            $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(),\r
-                                                     variable->getName(),\r
-                                                     variable->getType(), $1.line);\r
+            if (variable->getType().getQualifier().storage == EvqConst ) {\r
+                constUnion* constArray = variable->getConstUnionPointer();\r
+                TType t(variable->getType());\r
+                $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);\r
+            } else\r
+                $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(),\r
+                                                         variable->getName(),\r
+                                                         variable->getType(), $1.line);\r
+        }\r
     }\r
     ;\r
 \r
@@ -346,7 +361,7 @@ postfix_expression
             unionArray->setFConst(0.0f);\r
             $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line);\r
         } else {\r
-            TType newType = $1->getType();\r
+            TType newType($1->getType());\r
             newType.dereference();\r
             $$->setType(newType);\r
             // TODO: testing: write a set of dereference tests\r
@@ -400,7 +415,7 @@ postfix_expression
                     TString vectorString = *$3.string;\r
                     TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line);\r
                     $$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);\r
-                    $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size()));\r
+                    $$->setType(TType($1->getBasicType(), EvqTemporary, (int) vectorString.size()));\r
                 }\r
             }\r
         } else if ($1->isMatrix()) {\r
index aabab27..ab0c0db 100644 (file)
@@ -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);
index c797374..df6d1e7 100644 (file)
 //
 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;