Add grammar productions for adding 'invariant' to already declared variables.
authorJohn Kessenich <cepheus@frii.com>
Wed, 19 Jun 2013 20:44:17 +0000 (20:44 +0000)
committerJohn Kessenich <cepheus@frii.com>
Wed, 19 Jun 2013 20:44:17 +0000 (20:44 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22083 e7fa87d3-cd2b-0410-9028-fcbf551c1848

Test/120.vert
Test/specExamples.vert
glslang/Include/Types.h
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/glslang.y

index 9e8afbc..d0f64e4 100644 (file)
@@ -8,8 +8,9 @@ attribute vec4 attv4;
 uniform sampler2D s2D;
 invariant varying vec2 centTexCoord;
 invariant gl_Position;
-
+centroid gl_Position;
 centroid centroid foo;
+invariant gl_Position, gl_PointSize;
 
 void main()
 {
@@ -22,6 +23,8 @@ void main()
 
     float f[];
     int a = f.length();
+
+    gl_PointSize = 3.8;
 }
 
 uniform float initted = 3.4;
index c4b283c..bf148fa 100644 (file)
@@ -97,8 +97,8 @@ layout (binding=3) uniform atomic_uint c2;           // offset = 8
 layout (binding=2) uniform atomic_uint d2;           // offset = 4\r
 \r
 //layout (offset=4)                // error, must include binding\r
-layout (binding=1, offset=0)  a; // okay\r
-layout (binding=2, offset=0)  b; // okay\r
+//layout (binding=1, offset=0)  a; // okay\r
+//layout (binding=2, offset=0)  b; // okay\r
 //layout (binding=1, offset=0)  c; // error, offsets must not be shared\r
 //                                 //        between a and c\r
 //layout (binding=1, offset=2)  d; // error, overlaps offset 0 of a\r
index 02f991b..5fd3a7d 100644 (file)
@@ -154,6 +154,14 @@ inline TTypeList* NewPoolTTypeList()
        return new(memory) TTypeList;
 }
 
+typedef TVector<TString*> TIdentifierList;
+
+inline TIdentifierList* NewPoolTIdentifierList()
+{
+    void* memory = GlobalPoolAllocator.allocate(sizeof(TIdentifierList));
+    return new(memory) TIdentifierList;
+}
+
 //
 // TODO: memory: TArraySizes can be replaced by something smaller.
 // Almost all arrays could be handled by two sizes each fitting
@@ -236,7 +244,7 @@ public:
 
     bool isMemory() const
     {
-        return coherent || volatil || restrict || readonly || writeonly;
+        return shared || coherent || volatil || restrict || readonly || writeonly;
     }
     bool isInterpolation() const
     {
index 9e39634..a32ea21 100644 (file)
@@ -48,12 +48,15 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
             version(v), profile(p), forwardCompatible(fc), messages(m),
             contextPragma(true, false)
 {
+    // set all precision defaults to EpqNone, which is correct for all desktop types
+    // and for ES types that don't have defaults (thus getting an error on use)
     for (int type = 0; type < EbtNumTypes; ++type)
         defaultPrecision[type] = EpqNone;
 
     for (int type = 0; type < maxSamplerIndex; ++type)
         defaultSamplerPrecision[type] = EpqNone;
 
+    // replace with real defaults for those that have them
     if (profile == EEsProfile) {
         TSampler sampler;
         sampler.set(EbtFloat, Esd2D);
@@ -67,13 +70,11 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
             defaultPrecision[EbtUint] = EpqHigh;
             defaultPrecision[EbtFloat] = EpqHigh;
             defaultPrecision[EbtSampler] = EpqLow;
-            // TODO: functionality: need default precisions per sampler type
             break;
         case EShLangFragment:
             defaultPrecision[EbtInt] = EpqMedium;
             defaultPrecision[EbtUint] = EpqMedium;
             defaultPrecision[EbtSampler] = EpqLow;
-            // TODO: semantics: give error when using float in frag shader without default precision
             break;
         default:
             error(1, "INTERNAL ERROR", "unexpected language", "");
@@ -1607,6 +1608,36 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
     }
 }
 
+// For an identifier that is already declared, add more qualification to it.
+void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, const TString& identifier)
+{
+    TSymbol* existing = symbolTable.find(identifier);
+    TVariable* variable = existing ? existing->getAsVariable() : 0;
+    if (! variable) {
+        error(line, "identifier not previously declared", identifier.c_str(), "");
+
+        return;
+    }
+
+    if (qualifier.isAuxillary() || 
+        qualifier.isMemory() ||
+        qualifier.isInterpolation() ||
+        qualifier.storage != EvqTemporary ||
+        qualifier.precision != EpqNone) {
+        error(line, "cannot add this qualifier to an existing variable", identifier.c_str(), "");
+
+        return;
+    }
+
+    variable->getType().getQualifier().invariant = true;
+}
+
+void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, TIdentifierList& identifiers)
+{
+    for (unsigned int i = 0; i < identifiers.size(); ++i)
+        addQualifierToExisting(line, qualifier, *identifiers[i]);
+}
+
 //
 // Take the sequence of statements that has been built up since the last case/default,
 // put it on the list of top-level nodes for the current (inner-most) switch statement,
index d5a215a..04a80b5 100644 (file)
@@ -154,6 +154,8 @@ struct TParseContext {
     TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
     void addBlock(int line, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
+    void addQualifierToExisting(int line, TQualifier, const TString& identifier);
+    void addQualifierToExisting(int line, TQualifier, TIdentifierList&);
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
     TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body);
     void updateDefaults(int line, const TPublicType&, const TString* id);
index a7995f9..42e0635 100644 (file)
@@ -103,6 +103,7 @@ extern void yyerror(const char*);
             TTypeLine typeLine;\r
             TTypeList* typeList;\r
             TArraySizes arraySizes;\r
+            TIdentifierList* identifierList;\r
         };\r
     } interm;\r
 }\r
@@ -214,6 +215,8 @@ extern void yyerror(const char*);
 %type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype\r
 %type <interm> function_call_or_method function_identifier function_call_header\r
 \r
+%type <interm.identifierList> identifier_list\r
+\r
 %start translation_unit\r
 %%\r
 \r
@@ -1120,15 +1123,12 @@ declaration
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER SEMICOLON {\r
-        // TODO: functionality: track what variables are declared with INVARIANT\r
-        // precise foo;\r
-        // invariant foo;\r
+        parseContext.addQualifierToExisting($1.line, $1.qualifier, *$2.string);\r
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER identifier_list SEMICOLON {\r
-        // TODO: functionality: track what variables are declared with INVARIANT\r
-        // precise foo, bar;\r
-        // invariant foo, bar;\r
+        $3->push_back($2.string);\r
+        parseContext.addQualifierToExisting($1.line, $1.qualifier, *$3);\r
         $$ = 0;\r
     }\r
     ;\r
@@ -1144,8 +1144,12 @@ block_structure
 \r
 identifier_list\r
     : COMMA IDENTIFIER {\r
+        $$ = NewPoolTIdentifierList();\r
+        $$->push_back($2.string);\r
     }\r
     | identifier_list COMMA IDENTIFIER {\r
+        $$ = $1;\r
+        $$->push_back($3.string);\r
     }\r
     ;\r
 \r