From b76d6d64968b55bdefa0fa5360b88c44b09d3514 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Tue, 7 Jan 2014 18:14:48 +0000
Subject: [PATCH] GL_ARB_enhanced_layouts, part 1:  Track whether constants are
 literals, to enable version-specific checking of layout(... = literal) vs.
 layout(... = expression).

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24675 e7fa87d3-cd2b-0410-9028-fcbf551c1848
---
 Test/330.frag                                  | 12 ++++++++++++
 Test/baseResults/330.frag.out                  | 18 +++++++++++++++++-
 glslang/Include/intermediate.h                 |  5 ++++-
 glslang/Include/revision.h                     |  4 ++--
 glslang/MachineIndependent/Constant.cpp        |  2 +-
 glslang/MachineIndependent/Intermediate.cpp    |  4 +++-
 glslang/MachineIndependent/ParseHelper.cpp     | 18 +++++++++++++++---
 glslang/MachineIndependent/ParseHelper.h       |  2 +-
 glslang/MachineIndependent/Versions.cpp        |  4 +++-
 glslang/MachineIndependent/Versions.h          |  1 +
 glslang/MachineIndependent/glslang.y           | 18 +++++++-----------
 glslang/MachineIndependent/localintermediate.h |  2 +-
 12 files changed, 67 insertions(+), 23 deletions(-)

diff --git a/Test/330.frag b/Test/330.frag
index 22143f844..b90ae54e3 100644
--- a/Test/330.frag
+++ b/Test/330.frag
@@ -39,3 +39,15 @@ in gl_PerVertex {  // ERROR
 in gl_PerVertex {  // ERROR
     vec4 gl_FragCoord;
 };  // ERROR
+
+const int start = 6;
+layout(location = -2) in vec4 v1;         // ERROR
+layout(location = start + 2) in vec4 v2;  // ERROR
+layout(location = 4.7e10) in vec4 v20;    // ERROR
+
+#extension GL_ARB_enhanced_layouts : enable
+
+layout(location = start) in vec4 v3;
+layout(location = -2) in vec4 v4;         // ERROR
+layout(location = -start) in vec4 v5;     // ERROR
+layout(location = start*start - 2) in vec4 v6;
diff --git a/Test/baseResults/330.frag.out b/Test/baseResults/330.frag.out
index cb28b8ebc..0ada0598c 100644
--- a/Test/baseResults/330.frag.out
+++ b/Test/baseResults/330.frag.out
@@ -5,7 +5,14 @@ ERROR: 0:31: 'gl_' : reserved built-in name: gl_name
 ERROR: 0:32: 'gl_' : reserved built-in name: gl_i
 ERROR: 0:35: 'gl_in' : no declaration found for redeclaration 
 ERROR: 0:39: 'gl_FragCoord' : cannot redeclare a non block as a block 
-ERROR: 5 compilation errors.  No code generated.
+ERROR: 0:44: 'non-literal layout-id value' : not supported for this version or the enabled extensions 
+ERROR: 0:44: 'layout-id value' : cannot be negative 
+ERROR: 0:45: 'non-literal layout-id value' : not supported for this version or the enabled extensions 
+ERROR: 0:46: 'layout-id value' : scalar integer expression required 
+ERROR: 0:46: 'location' : location is too large 
+ERROR: 0:51: 'layout-id value' : cannot be negative 
+ERROR: 0:52: 'layout-id value' : cannot be negative 
+ERROR: 12 compilation errors.  No code generated.
 
 
 ERROR: node is still EOpNull!
@@ -45,6 +52,15 @@ ERROR: node is still EOpNull!
 0:?     'varyingVar' (smooth in 4-component vector of float)
 0:?     '__anon__0' (in block{in 4-component vector of float gl_Color, })
 0:?     'gl_name' (in block{in int gl_i})
+0:?     'start' (const int)
+0:?       6 (const int)
+0:?     'v1' (smooth in 4-component vector of float)
+0:?     'v2' (layout(location=8 ) smooth in 4-component vector of float)
+0:?     'v20' (smooth in 4-component vector of float)
+0:?     'v3' (layout(location=6 ) smooth in 4-component vector of float)
+0:?     'v4' (smooth in 4-component vector of float)
+0:?     'v5' (smooth in 4-component vector of float)
+0:?     'v6' (layout(location=34 ) smooth in 4-component vector of float)
 
 
 Linked fragment stage:
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index 6b0570a29..b73083a76 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -494,15 +494,18 @@ protected:
 
 class TIntermConstantUnion : public TIntermTyped {
 public:
-    TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua) { }
+    TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { }
     const TConstUnionArray& getConstArray() const { return unionArray; }
     virtual       TIntermConstantUnion* getAsConstantUnion()       { return this; }
     virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
     virtual void traverse(TIntermTraverser*);
     virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
     virtual TIntermTyped* fold(TOperator, const TType&) const;
+    void setLiteral() { literal = true; }
+    bool isLiteral() const { return literal; }
 protected:
     const TConstUnionArray unionArray;
+    bool literal;  // true if node represents a literal in the source code
 };
 
 //
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index a24f55d53..90a7e2716 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build
 // going.  However, if it is not updated, it can be a version behind.
 
-#define GLSLANG_REVISION "24664"
-#define GLSLANG_DATE     "2014/01/06 14:27:56"
+#define GLSLANG_REVISION "24674"
+#define GLSLANG_DATE     "2014/01/07 10:44:41"
diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp
index 7e045b6b1..801cf1d10 100644
--- a/glslang/MachineIndependent/Constant.cpp
+++ b/glslang/MachineIndependent/Constant.cpp
@@ -85,7 +85,7 @@ namespace glslang {
 //
 // Returns a new node representing the result.
 //
-TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* constantNode) const 
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* constantNode) const
 {
     // For most cases, the return type matches the argument type, so set that
     // up and just code to exceptions below.
diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index eaa070eec..952d103e7 100644
--- a/glslang/MachineIndependent/Intermediate.cpp
+++ b/glslang/MachineIndependent/Intermediate.cpp
@@ -782,10 +782,12 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
 // Returns the constant union node created.
 //
 
-TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, TSourceLoc loc)
+TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, TSourceLoc loc, bool literal)
 {
     TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
     node->setLoc(loc);
+    if (literal)
+        node->setLiteral();
 
     return node;
 }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 00b8b889b..12cfb59f4 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -2808,12 +2808,24 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
 
 // Put the id's layout qualifier value into the public type.  This is before we know any
 // type information for error checking.
-void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id, int value)
+void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id, const TIntermTyped* node)
 {
+    const char* feature = "layout-id value";
+    const char* nonLiteralFeature = "non-literal layout-id value";
+
+    integerCheck(node, feature);
+    const TIntermConstantUnion* constUnion = node->getAsConstantUnion();
+    assert(constUnion);
+    int value = node->getAsConstantUnion()->getConstArray()[0].getIConst();
+
+    if (! constUnion->isLiteral()) {
+        requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature);
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, nonLiteralFeature);
+    }
+
     if (value < 0) {
-        error(loc, "cannot be negative", "layout qualifier value", "");
+        error(loc, "cannot be negative", feature, "");
         return;
-        // TODO: 4.4: test the above, once expressions are allowed; until then, can't even express a negative location
     }
 
     std::transform(id.begin(), id.end(), id.begin(), ::tolower);
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index b8c790639..a2dcc605e 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -148,7 +148,7 @@ public:
     void constantIndexExpressionCheck(TIntermNode*);
 
     void setLayoutQualifier(TSourceLoc, TPublicType&, TString&);
-    void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int);
+    void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, const TIntermTyped*);
     void mergeObjectLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src, bool inheritOnly);
     void layoutTypeCheck(TSourceLoc, const TSymbol&);
     void layoutQualifierCheck(TSourceLoc, const TQualifier&);
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 6fc97f744..5fe2de385 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -162,6 +162,7 @@ void TParseContext::initializeExtensionBehavior()
     extensionBehavior[GL_ARB_gpu_shader5]              = EBhDisablePartial;
     extensionBehavior[GL_ARB_separate_shader_objects]  = EBhDisable;
     extensionBehavior[GL_ARB_tessellation_shader]      = EBhDisable;
+    extensionBehavior[GL_ARB_enhanced_layouts]         = EBhDisable;
 }
 
 // Get code that is not part of a shared symbol table, is specific to this shader,
@@ -184,7 +185,8 @@ const char* TParseContext::getPreamble()
             "#define GL_ARB_texture_gather 1\n"
             "#define GL_ARB_gpu_shader5 1\n"
             "#define GL_ARB_separate_shader_objects 1\n"
-            "#define GL_ARB_tessellation_shader 1\n";
+            "#define GL_ARB_tessellation_shader 1\n"
+            "#define GL_ARB_enhanced_layouts 1\n";
     }
 }
 
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index d0997b816..e7ccd2e68 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -86,6 +86,7 @@ const char* const GL_ARB_texture_gather           = "GL_ARB_texture_gather";
 const char* const GL_ARB_gpu_shader5              = "GL_ARB_gpu_shader5";
 const char* const GL_ARB_separate_shader_objects  = "GL_ARB_separate_shader_objects";
 const char* const GL_ARB_tessellation_shader      = "GL_ARB_tessellation_shader";
+const char* const GL_ARB_enhanced_layouts         = "GL_ARB_enhanced_layouts";
 
 } // end namespace glslang
 
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index a1dda8723..11d603859 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -228,29 +228,29 @@ primary_expression
     | INTCONSTANT {
         TConstUnionArray unionArray(1);
         unionArray[0].setIConst($1.i);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.loc, true);
     }
     | UINTCONSTANT {        
         parseContext.fullIntegerCheck($1.loc, "unsigned literal");
         TConstUnionArray unionArray(1);
         unionArray[0].setUConst($1.u);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.loc, true);
     }
     | FLOATCONSTANT {
         TConstUnionArray unionArray(1);
         unionArray[0].setDConst($1.d);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.loc, true);
     }
     | DOUBLECONSTANT {
         parseContext.doubleCheck($1.loc, "double literal");
         TConstUnionArray unionArray(1);
         unionArray[0].setDConst($1.d);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtDouble, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtDouble, EvqConst), $1.loc, true);
     }
     | BOOLCONSTANT {
         TConstUnionArray unionArray(1);
         unionArray[0].setBConst($1.b);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.loc, true);
     }
     | LEFT_PAREN expression RIGHT_PAREN {
         $$ = $2;
@@ -1110,13 +1110,9 @@ layout_qualifier_id
         $$.init($1.loc);
         parseContext.setLayoutQualifier($1.loc, $$, *$1.string);
     }
-    | IDENTIFIER EQUAL INTCONSTANT {
+    | IDENTIFIER EQUAL constant_expression {
         $$.init($1.loc);
-        parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3.i);
-    }
-    | IDENTIFIER EQUAL UINTCONSTANT {
-        $$.init($1.loc);
-        parseContext.setLayoutQualifier($1.loc, $$, *$1.string, (int)$3.u);
+        parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3);
     }
     | SHARED { // because "shared" is both an identifier and a keyword
         $$.init($1.loc);
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 2ce1f1fdc..eb85dafa2 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -96,7 +96,7 @@ public:
     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
-    TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc);
+    TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc, bool literal = false);
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
-- 
GitLab